个人理解设计模式是为了实现代码的最大复用功能或者用户需求需要增加或者更改时我们只需要改动最少量的代码。
下面是一段绘图程序,鼠标的抬起和落下动作绘制图形,我们先来看下使用分解方法来实现代码功能
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->width = width;
this->height = height;
}
};
//增加一个类
class circle //1处
{
};
using namespace std;
class Mainform :public Form {
private:
Point p1;
Point p2;
vector<Line>lineVector; //存储的对像,不需要多肽类
vector<Rect>rectVector;// 分解法 需要设计不同的类型
vector<circle>circleVector; //2处
public:
Mainform()
{}
protected:
virtual void OnMouseDown(const MouseEventArgs &e);
virtual void OnMouseUp(const MouseEventArgs &e);
virtual void OnPaint(const PaintEventArgs& e);
};
void Maiform::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);
linevVector.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);
recvtVector.push_back(rect);
}
else if (...) //3处
{
circleVector。push_back()
}
this->ReFresh();
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 (...) //针对圆形.. 4处
{
.graphics.DrawCircle();
}
Form::Onpaint(e);
}
假如说客户突然要增加一个绘制圆形的需求我们使用分解法需要修改四处代码,大大的增了修改代码的工作量。
我们再来看下使用抽象的方法
#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 Graphics& 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;
}
virtual void Draw(const Graphics&g)
{
g.DrawRectangle(Pens, Red,
LeftUp, width, height);
}
}
class circle::public Shape//1处
{
};
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 Maiform::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);
ShapeVector.push_back(new Line(p1,p2)); //堆对象指针 在合适的地方delete
}
else if (rdoRect.Checked)
{
int width = abs(p2.x - p1.x);
int height = abs(p2.y - p1.y);
//Rect rect(p1, width, height);
ShapeVector.push_back(new Rect(p1,width,height));//堆像指针
}
else if (circle) // 2处
{}
this->ReFresh();
Form::OnMouseUp(e);
}
void MainForm::OnPaint(const PaintEventArgs&e)
{
for (int i = 0; i < shapeVector.size(); i++)
{
shapeVector[i]->Draw(e.Graphics);//多态调用,各负其责 draw是虚方法
}
Form::OnPaint(e);
}
只需要修改两处,由此可见抽象的方法大大提高了代码的复用性 。
1.依赖倒置原则(DIP) 高层
高层模块(稳定)不依赖于低层模块(变化)。二者都应该依赖于抽象(稳定) mainForm->
低层 高层 抽象 隔离(细节)
(Line,Rect), mainForm->Shape<-Line,Rect
抽象(稳定)不依赖于实现细节(变化)实现细节变化依赖于抽象
面向对象设计原则原则2.
2.开放封闭原则(OCP)
对扩展开放,对更改封闭
类模块可扩展,但是不可修改。 上面抽象类绘图方法的代码块 只需扩展一个绘制圆形类
--写于2022-12-5 9:48 pm
(啥时能税后月薪6万啊)