设计模式第一讲--设计模式简介
1. 课程目标
(1)理解松耦合设计思想
(2)掌握面向对象设计原则
(3)掌握重构技法改善设计
(4)掌握GOF核心设计模式
2. 《设计模式:可复用面向对象软件的基础》
可复用是设计模式的目标,面向对象是方法。通常说的设计模式默认为面向对象的设计模式,但这并不意味着设计模式就等于面向对象的设计模式。
3. 底层思维:向下,如何把握机器底层从围观理解对象构造
语言构造、编译转换、内存模型、运行时机制。
抽象思维:向上,如何将我们的周围世界抽象为程序代码
面向对象、组件封装、设计模式、架构模式。
深入理解面向对象:
向下:深入理解三大面向对象机制
封装:隐藏内部实现
继承:复用现有代码
多态:修改对象行为
向上:深刻把握面向对象机制所带来的抽象意义,理解如何使用这些机制来表达现实世界,掌握什么是“好的面向对象设计”。
4. 如何解决复杂性?
(1)分解 分而治之,将大问题分解成多个小问题,将复杂问题分解为多个简单问题。
(2)抽象 更高层次来讲,人们处理复杂性有一个通用的技术,即抽象。由于不能掌握全部的复杂对象,我们选择忽视它的非本质细节,而去处理泛化和理想化了的对象模型。
5.假设在一个界面上可以绘制线条和矩形
(1)用分解的思路实现,伪代码如下:
shape.h文件内容
#pragma once
class Point
{
public:
int x;
int y;
};
class Line
{
public:
Point start;
Point end;
Line(const Point& start, const Point& end)
{
this->start = start;
this->end = end;
}
};
class Rect
{
public:
Point leftUp;
int width;
int height;
Rect(const Point& leftUP, int width, int height)
{
this->leftUp = leftUP;
this->height = height;
this->width = width;
}
};
每一个形状对应各自的类。
MainForm.cpp中的内容
#include "Shape.h"
#include<vector>
using namespace std;
class MainForm :public Form
{
private:
Point p1; //表示鼠标按下和抬起的点
Point p2;
vector<Line> lineVector;
vector<Rect> rectVector;
public:
MainForm()
{
//...
}
protected:
virtual void OnMouseDown(const MouseEventArgs& e); //鼠标按下
virtual void OnMouseUp(const MouseEventArgs& e); //鼠标抬起
virtual void OnPaint(const PaintEventArgs& e); //界面刷新
};
void MainForm::OnMouseDown(const MouseEventArgs& e)
{
p1.x = e.X;
p1.y = e.Y;
//...
Form::OnMouseDown(e);
}
void MainForm::OnMouseUp(const MouseEventArgs& e)
{
p2.x = e.X;
p2.y = e.Y;
if (rdoLine.Checked)
{
Line Line(p1, p2);
LineVector.push_back(line);
}
else if (rdoRect.Checked)
{
int width = abs(p2.x - p1.x);
int height = abs(p2.y - p1.y);
Rect rect(p1, width, height);
rectVector.push_back(rect);
}
//...
this->Refresh(); //系统会调用OnPaint
Form::OnMouseUp(e);
}
void MainForm::OnPaint(const PaintEventArgs& e)
{
//针对直线
for (int i = 0; i < lineVector.size(); i++)
{
e.Graphics.DrawLine(Pens.red,
lineVector[i].start.x,
lineVector[i].start.y,
lineVector[i].end.x,
lineVector[i].end.y);
}
//针对矩形
for (int i = 0; i < rectVector.size(); i++)
{
e.Graphics.DrawRectangle(Pens.red,
rectVector[i].leftUp,
rectVector[i].width,
rectVector[i].height);
}
//...
Form::OnPaint(e);
}
现在有一个需求,要求可以再界面上绘制圆形。
为了实现这个目标,书写的代码如下:
shape.h文件
#pragma once
class Point
{
public:
int x;
int y;
};
class Line
{
public:
Point start;
Point end;
Line(const Point& start, const Point& end)
{
this->start = start;
this->end = end;
}
};
class Rect
{
public:
Point leftUp;
int width;
int height;
Rect(const Point& leftUP, int width, int height)
{
this->leftUp = leftUP;
this->height = height;
this->width = width;
}
};
//新加代码
class Circle
{
public:
Point Center;
int Radius;
Circle(const Point& center, int radius)
{
this->Center = center;
this->Radius = radius;
}
};
MainForm.cpp文件内容
#include "Shape.h"
#include<vector>
using namespace std;
class MainForm :public Form
{
private:
Point p1; //表示鼠标按下和抬起的点
Point p2;
vector<Line> lineVector;
vector<Rect> rectVector;
vector<Circle> circleVector;
public:
MainForm()
{
//...
}
protected:
virtual void OnMouseDown(const MouseEventArgs& e); //鼠标按下
virtual void OnMouseUp(const MouseEventArgs& e); //鼠标抬起
virtual void OnPaint(const PaintEventArgs& e); //界面刷新
};
void MainForm::OnMouseDown(const MouseEventArgs& e)
{
p1.x = e.X;
p1.y = e.Y;
//...
Form::OnMouseDown(e);
}
void MainForm::OnMouseUp(const MouseEventArgs& e)
{
p2.x = e.X;
p2.y = e.Y;
if (rdoLine.Checked)
{
Line Line(p1, p2);
LineVector.push_back(line);
}
else if (rdoRect.Checked)
{
int width = abs(p2.x - p1.x);
int height = abs(p2.y - p1.y);
Rect rect(p1, width, height);
rectVector.push_back(rect);
}
else if (rdoCircle.Checked)
{
Point center;
center.x = (p1.x + p2.x) / 2;
center.y = (p1.y + p2.y) / 2;
int radius = sqrt(pow(abs(p1.x - p2.x), 2) + pow(abs(p1.y - p2.y), 2)) / 2;
Circle circle(center,radius);
circleVector.push_back(circle);
}
//...
this->Refresh(); //系统会调用OnPaint
Form::OnMouseUp(e);
}
void MainForm::OnPaint(const PaintEventArgs& e)
{
//针对直线
for (int i = 0; i < lineVector.size(); i++)
{
e.Graphics.DrawLine(Pens.red,
lineVector[i].start.x,
lineVector[i].start.y,
lineVector[i].end.x,
lineVector[i].end.y);
}
//针对矩形
for (int i = 0; i < rectVector.size(); i++)
{
e.Graphics.DrawRectangle(Pens.red,
rectVector[i].leftUp,
rectVector[i].width,
rectVector[i].height);
}
//针对圆形
for (int i = 0; i < circleVector.size(); i++)
{
e.Graphics.DrawCircle(Pens.red,
rectVector[i].Center,
rectVector[i].Radius);
}
//...
Form::OnPaint(e);
}
(2)抽象的思路实现界面上可以绘制直线和矩形的功能
Shape1.h文件内容
#pragma once
class Shape
{
public:
virtual void Draw(const Graphics& g) = 0;
virtual ~Shape() {}
};
class Point
{
public:
int x;
int y;
};
class Line : public Shape
{
public:
Point start;
Point end;
Line(const Point& start, const Point& end)
{
this->start = start;
this->end = end;
}
//实现自己的Draw,负责画自己
virtual void Draw(const Graphic& g)
{
g.DrawLine(Pens.red, start.x, start.y, end.x, end.y);
}
};
class Rect :public Shape
{
public:
Point leftUp;
int width;
int height;
Rect(const Point& leftUp, int width, int height)
{
this->leftUp = leftUp;
this->width = width;
this->height = height;
}
//实现自己的Draw,负责画自己
virtual void Draw(const Graphics& g)
{
g.DrawRectangle(Pens.red, leftUp, width, height);
}
};
创建名为Shape的基类,线条类和矩形类都继承Shape基类,其再各自的类中实现Draw方法。
MainForm1.cpp
#include "Shape1.h"
#include<vector>
using namespace std;
class MainForm : public Form
{
private:
Point p1;
Point p2;
//针对所有形状
vector<Shape*> shapeVector; //析构的时候需要释放这个地方的内存
public:
MainForm()
{
//...
}
protected:
virtual void OnMouseDown(const MouseEventArgs& e); //鼠标按下
virtual void OnMouseUp(const MouseEventArgs& e); //鼠标抬起
virtual void OnPaint(const PaintEventArgs& e); //界面刷新
};
void MainForm::OnMouseDown(const MouseEventArgs& e)
{
p1.x = e.X;
p1.y = e.Y;
//...
Form::OnMouseDown(e);
}
void MainForm::OnMouseUp(const MouseEventArgs& e)
{
p2.x = e.X;
p2.y = e.Y;
if (rdoLine.Checked)
{
shapeVector.push_back(new Line(p1, p2));
}
else if (rdoRect.Checked)
{
int width = abs(p2.x - p1.x);
int height = abs(p2.y - p1.y);
shapeVector.push_back(new Rect(p1, width, height));
}
//...
this->Refresh(); //系统会调用OnPaint
Form::OnMouseUp(e);
}
void MainForm::OnPaint(const PaintEventArgs& e)
{
//针对所有形状
for (int i = 0; i < shapeVector.size(); i++)
{
//多态调用,各负其责
shapeVector[i]->Draw(e.Graphics);
}
//...
Form::OnPaint(e);
}
那这个时候,只需要再MainForm类中创建存储Shape*的vector数组就好,不必针对每一中类型创建vector了。
那现在我们有相同的需求,都是在界面上可以绘制圆形。对应修改的代码如下:
Shape1.h
#pragma once
class Shape
{
public:
virtual void Draw(const Graphics& g) = 0;
virtual ~Shape() {}
};
class Point
{
public:
int x;
int y;
};
class Line : public Shape
{
public:
Point start;
Point end;
Line(const Point& start, const Point& end)
{
this->start = start;
this->end = end;
}
//实现自己的Draw,负责画自己
virtual void Draw(const Graphic& g)
{
g.DrawLine(Pens.red, start.x, start.y, end.x, end.y);
}
};
class Rect :public Shape
{
public:
Point leftUp;
int width;
int height;
Rect(const Point& leftUp, int width, int height)
{
this->leftUp = leftUp;
this->width = width;
this->height = height;
}
//实现自己的Draw,负责画自己
virtual void Draw(const Graphics& g)
{
g.DrawRectangle(Pens.red, leftUp, width, height);
}
};
class Circle :public Shape
{
public:
Point Center;
int Radius;
Circle(const Point& center, int radius)
{
this->Center = center;
this->Radius = radius;
}
// 实现自己的Draw,负责画自己
virtual void Draw(const Graphics & g)
{
g.DrawCircle(Pens.red, Center, Radius);
}
};
MainForm.cpp
#include "Shape1.h"
#include<vector>
using namespace std;
class MainForm : public Form
{
private:
Point p1;
Point p2;
//针对所有形状
vector<Shape*> shapeVector; //析构的时候需要释放这个地方的内存
public:
MainForm()
{
//...
}
protected:
virtual void OnMouseDown(const MouseEventArgs& e); //鼠标按下
virtual void OnMouseUp(const MouseEventArgs& e); //鼠标抬起
virtual void OnPaint(const PaintEventArgs& e); //界面刷新
};
void MainForm::OnMouseDown(const MouseEventArgs& e)
{
p1.x = e.X;
p1.y = e.Y;
//...
Form::OnMouseDown(e);
}
void MainForm::OnMouseUp(const MouseEventArgs& e)
{
p2.x = e.X;
p2.y = e.Y;
if (rdoLine.Checked)
{
shapeVector.push_back(new Line(p1, p2));
}
else if (rdoRect.Checked)
{
int width = abs(p2.x - p1.x);
int height = abs(p2.y - p1.y);
shapeVector.push_back(new Rect(p1, width, height));
}
else if (rdoCircle.Checked)
{
Point center;
center.x = (p1.x + p2.x) / 2;
center.y = (p1.y + p2.y) / 2;
int radius = sqrt(pow(abs(p1.x - p2.x), 2) + pow(abs(p1.y - p2.y), 2)) / 2;
shapeVector.push_back(new Circle(center, radius));
}
//...
this->Refresh(); //系统会调用OnPaint
Form::OnMouseUp(e);
}
void MainForm::OnPaint(const PaintEventArgs& e)
{
//针对所有形状
for (int i = 0; i < shapeVector.size(); i++)
{
//多态调用,各负其责
shapeVector[i]->Draw(e.Graphics);
}
//...
Form::OnPaint(e);
}
可以看的出,对应相同的功能,面向对象的设计方式比分解的设计方式改动要少的多。
代码的复用性也好的多。
posted on 2021-11-25 08:36 xcxfury001 阅读(38) 评论(0) 收藏 举报
浙公网安备 33010602011771号