理解松耦合的设计思想。

理解设计原则比掌握某一个具体的设计模式更重要。

设计模式伴随的方法 —— 重构。

面向对象的设计模式 —— GOF 23 种为主干。


为什么要设计模式?解决不断重复的问题。可复用是面向对象的目标。94年《设计模式:可复用面向对象软件的基础》。

底层思维:向下,从机器底层微观上理解对象构造。1. 语言构造 2. 编译转换 3. 内存模型 4. 运行机制。 语言层面上的对象机制:封装,继承,多态。

抽象思维:向上,现实世界抽象为程序代码。1. 架构领域的架构模式; 2. 数据库领域的数据库模式;3. 组件封装; 4. 面向对象。 掌握好什么是“好的面向对象设计”。


解决复杂问题的方法:1.分解 2.抽象

分解

大问题分解为若干个小问题,复杂问题分解为若干个简单的问题。C语言,结构性语言是典型的分解思想。

代码示例:

#include <iostream>
#include <vector>

using namespace std;


/****************************/

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
{

};

/*************************/

enum class Shape
{
Line,
Rect,
Circle,
};

class MainForm
{
public:
MainForm() {}

virtual void OnMouseDown(const int x, const int y)
{
p1.x = x;
p1.y = y;
}
virtual void OnMouseUp(const int x, const int y, Shape shape)
{
p2.x = x;
p2.y = y;

switch (shape)
{
case Shape::Line:
{
lineVector.push_back(Line(p1, p2));
}
break;
case Shape::Rect:
{
rectVector.push_back(Rect(p1, p2.x - p1.x, p2.y - p1.y));
}
break;
// 改变
case Shape::Circle:
{
// ....
}
break;
default:
break;
}

}
virtual void OnPaint()
{//刷新

// 针对直线
for (int i = 0; i < lineVector.size(); i++) {
cout << "直线,起点(" << lineVector[i].start.x << "," << lineVector[i].start.y << ") " <<
"终点(" << lineVector[i].end.x << "," << lineVector[i].end.y << ")" << endl;
}

cout << endl;

// 针对矩形
for (int i = 0; i < rectVector.size(); i++) {
cout << "矩形,起点(" << rectVector[i].leftUp.x << "," << rectVector[i].leftUp.y << ")" <<
"宽度:" << rectVector[i].width << "高度:" << rectVector[i].height << endl;
}

// 改变 针对圆
for (;;) {
// ....
break;
}
}

private:
Point p1;
Point p2;

// 数据结构存放
vector<Line> lineVector;
vector<Rect> rectVector;
//改变
vector<Circle> circleVector;
};

/*********************************/

int main()
{
MainForm mainForm;

// 画直线
mainForm.OnMouseDown(0, 0);
mainForm.OnMouseUp(100, 100, Shape::Line);
mainForm.OnMouseDown(0, 0);
mainForm.OnMouseUp(110, 110, Shape::Line);

// 画矩形
mainForm.OnMouseDown(10, 10);
mainForm.OnMouseUp(1000, 1000, Shape::Rect);
mainForm.OnMouseDown(100, 100);
mainForm.OnMouseUp(1000, 1000, Shape::Rect);

// 刷新
mainForm.OnPaint();

getchar();
return 0;
}

输出:

直线,起点(0,0) 终点(100,100)
直线,起点(0,0) 终点(110,110)

矩形,起点(10,10)宽度:990高度:990
矩形,起点(100,100)宽度:900高度:900

如上,如果要新增一个画圆的功能,有很多地方需要去修改改变代码。

抽象

处理复杂性有一个通用的技术,即抽象。由于不能掌握全部的复杂对象,我们选择忽视它的非本质细节,而去处理泛化和理想化了的对象模型。

面向对象的设计模式,基本上是围绕着抽象这个概念去进行的。

代码示例:

#include <iostream>
#include <vector>
#include <math.h>

using namespace std;


/****************************/

class Point {
public:
int x;
int y;
};

// 接口
class IShape {
public:
virtual void Draw() = 0;
virtual ~IShape() { }
};

// 直线
class Line : public IShape
{
public:
Point start;
Point end;

Line(const Point &start, const Point &end)
{
this->start = start;
this->end = end;
}

// 自己画自己,类功能,各司其职。
virtual void Draw() override
{
cout << "直线,起点(" << start.x << "," << start.y << ") " <<
"终点(" << end.x << "," << end.y << ")" << endl;
}
};

// 矩形
class Rect : public IShape
{
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() override
{
cout << "矩形,起点(" << leftUp.x << "," << leftUp.y << ")" <<
"宽度:" << width << " 高度:" << height << endl;
}
};


// 增加一个类
class Circle : public IShape
{
public:
Point m_center;
int R;
Circle(const Point &center, int r) :m_center(center), R(r) {}

virtual void Draw() override
{
cout << "圆形,圆心(" << m_center.x << "," << m_center.y << ")" <<
"半径:" << R << endl;
}
};

/*************************/

enum class ShapeType
{
Line,
Rect,
Circle,
};

class MainForm
{
public:
MainForm() {}
virtual ~MainForm()
{
vector<IShape *>::iterator itor = m_ShapeVector.begin();
while (itor != m_ShapeVector.end()) {
delete (*itor);
*itor = nullptr;
itor = m_ShapeVector.erase(itor);
itor++;
}
}

virtual void OnMouseDown(const int x, const int y)
{
p1.x = x;
p1.y = y;
}
virtual void OnMouseUp(const int x, const int y, ShapeType shape)
{
p2.x = x;
p2.y = y;

switch (shape)
{
case ShapeType::Line:
{
m_ShapeVector.push_back(new Line(p1, p2));
}
break;
case ShapeType::Rect:
{
m_ShapeVector.push_back(new Rect(p1, p2.x - p1.x, p2.y - p1.y));
}
break;
// 改变 后面这里用工厂模式,都不用修改
case ShapeType::Circle:
{
double r = sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
m_ShapeVector.push_back(new Circle(p1, static_cast<int>(r)));
}
break;
default:
break;
}

}
virtual void OnPaint()
{//刷新
for (int i = 0; i < m_ShapeVector.size(); i++) {
m_ShapeVector[i]->Draw(); // 多态调用
}
}

private:
Point p1;
Point p2;

// 数据结构存放
vector<IShape *> m_ShapeVector;
};

/*********************************/

int main()
{
MainForm mainForm;

// 画直线
mainForm.OnMouseDown(0, 0);
mainForm.OnMouseUp(100, 100, ShapeType::Line);
mainForm.OnMouseDown(0, 0);
mainForm.OnMouseUp(110, 110, ShapeType::Line);

// 画矩形
mainForm.OnMouseDown(10, 10);
mainForm.OnMouseUp(1000, 1000, ShapeType::Rect);
mainForm.OnMouseDown(100, 100);
mainForm.OnMouseUp(1000, 1000, ShapeType::Rect);

// 画圆
mainForm.OnMouseDown(100, 100);
mainForm.OnMouseUp(1000, 1000, ShapeType::Circle);
mainForm.OnMouseDown(101, 101);
mainForm.OnMouseUp(1100, 1100, ShapeType::Circle);

// 刷新
mainForm.OnPaint();

getchar();
return 0;
}

输出:

直线,起点(0,0) 终点(100,100)
直线,起点(0,0) 终点(110,110)
矩形,起点(10,10)宽度:990 高度:990
矩形,起点(100,100)宽度:900 高度:900
圆形,圆心(100,100)半径:1272
圆形,圆心(101,101)半径:1412

抽象能够很好的应对引入一种变化的情况。复用性比较好,分解改的地方太多。

什么是好的软件设计?软件设计的金科玉律:复用!



参考:GeekBand