设计模式
说法:"每一个模式描述了在我们周围不断重复发生的问题以及该问题的解决方案的核心"
推荐书籍:《设计模式:可复用面向对象软件的基础》
《面向对象分析和设计》
目标:可复用
手法:面向对象
当然架构领域也有设计模式,比如:MVC、MVP、MVVM
数据库领域也有自己的设计模式
但是本设计模式主要是面向对象设计模式
需要把握面向对象带来的抽象意义 理解如何利用这些机制来表达现实世界
软件设计复杂的根本原因: 变化
- 客户需求
- 技术平台
- 开发团队
- 市场环境
如何解决复杂性:
- 分解
- 抽象
对于分解:分而治之
对于抽象:由于不能掌握全部的复杂抽象, 因此去忽视非本质特点, 去泛化和理想化对象模型
结构化和面向对象
以一个简单的画图工具的demo为例子, 因为仅做例子, 所以
- 伪码
- 成员全公开
- 没有分文件
以分解思想进行设计
shape.h
c++
class Point
{
public:
int x;
int y;
}
区别:
哪种设计更好?
如果静态的看的话, 确实看不出
但是假如, 发生了变化
客户需求变了
这个时候需要能画圆形
那么第一种实现方法, 需要增加圆形的类, 需要修改mainForm.cpp, 增加一个vector
且, 需要修改OnMouseUp函数, 增加一个判断, 如果是画圆形, 则需要创建一个Circle对象, 并加入到vector中
且, 需要修改OnPaint函数, 增加一个判断, 如果是画圆形, 则需要调用Circle的Draw函数
而第二种做法:
- 增加一个Circle类
- 修改OnMouseUp函数, 增加一个判断, 如果是画圆形, 则需要创建一个Circle对象, 并加入到vector中(工厂模式可以不用)
c++
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;
}
}
这个时候假设我们有一个界面:
mainForm.cpp
c++
class MainForm : public Form
{
private:
Point p1;
Point p2;
vector<Line> lineVector;
vector<Rect> rectVector;
public:
MainForm()
{
// code...
}
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;
// code...
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);
}
// code...
this->Refresh();
Form::OnMouseUp(e);
}
void MainForm::OnPaint(const PaintEventArgs& e)
{
// 线
for (int i = 0; i < lineVector.size(); i ++ )
{
e.Graphics.DrawLine(pPens.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(pPens.Red,
rectVector[i].leftUp,
rectVector[i].width,
rectVector[i].height);
}
// code...
Form::OnPaint(e);
}
抽象方法:
shape.h
c++
class Shape
{
public:
virtual void Draw(const Graphics& g) = 0;
virtual void ~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;
}
virtual void Draw(const Graphics& g)
{
g.DrawLine(pPens.Red, start.x, start.y, end.x, end.y);
}
}
class Rect: public Shape
{
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(pPens.Red, leftUp, width, height);
}
}
mainForm.cpp
c++
class MainForm : public Form
{
private:
Point p1;
Point p2;
vector<Shape*> shapeVector;
public:
MainForm(){ /* code... */}
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;
// code...
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));
}
// code...
this->Refresh();
Form::OnMouseUp(e);
}
void MainForm::OnPaint(const PaintEventArgs& e)
{
for (int i = 0; i < shapeVector.size(); i ++ )
{
shapeVector[i]->Draw(e.Graphics); // 多态调用, 各司其职
}
// code...
Form::OnPaint(e);
}
哪种设计更好?
如果静态的看的话, 确实看不出
但是假如, 发生了变化
客户需求变了
这个时候需要能画圆形
那么第一种实现方法, 需要增加圆形的类, 需要修改mainForm.cpp, 增加一个vector
且, 需要修改OnMouseUp函数, 增加一个判断, 如果是画圆形, 则需要创建一个Circle对象, 并加入到vector中
且, 需要修改OnPaint函数, 增加一个判断, 如果是画圆形, 则需要调用Circle的Draw函数
而第二种做法:
- 增加一个Circle类
- 修改OnMouseUp函数, 增加一个判断, 如果是画圆形, 则需要创建一个Circle对象, 并加入到vector中(工厂模式可以不用)
简单来说, 抽象就是统一处理(多态)
也就是当需求变化的时候, 我可以继续复用
因此, 引出设计模式的核心理念------复用