=======================================================================
设计模式推荐一个在线视频,讲的很不错,链接如下:
https://www.bilibili.com/video/BV1Yr4y157Ci?vd_source=f42f5dca8fddf859c6fee556cb2c3dbf
推荐书籍:
《设计模式-可复用面向对象的软件基础》
《Head First设计模式》
《大话设计模式》
=======================================================================
目标:
理解松耦合设计思想
掌握面向对象设计原则
掌握重构技法改善设计
掌握GOF核心设计模式
什么是设计模式
“每一个模式描述了一个在我们周围不断重复发生的问题以及该问题的解决方案核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”---Chritopher Alexander
GOF设计模式
《设计模式:可复用面向对象软件的基础》---书中描述了23中经典面向对象设计模式,创立了模式在软件中地位。
面向对象
底层思维:向下,如何把握机器底层从微观理解对象构造
语言构造、编译转换、内存模型、运行时机制
抽象思维:向上,如何将我们的周围世界抽象为程序代码
面向对象、组件封装、设计模式、架构模式
深入理解面向对象
向下:深入理解三大面向对象机制
封装:隐藏内部实现
继承:复用现有代码
多态:改写对象行为
向上:深刻把握面向对象机制所带来的抽象意义,如何理解使用这些机制来表达现实世界,掌握什么是“好的面向对象设计”。
软件设计固有的复杂性
建筑商从来不会去想给一栋已建好的100层高的楼房底下在新建一个小地下室---这样做花费极大而且注定要失败。然而令人惊奇的是,软件系统的用户在要求作为类似改变时却不会仔细考虑,而且他们认为这只是需要简单编程的事。---- Objective-Oriented Analysis and Design with Applications
软件设计复杂的根本原因
变化
客户需求的变化
技术平台的变化
开发团队的变化
市场环境的变化
。。。。。。
如何解决复杂性
分解:
人们面对复杂性有一个常见的做法:即分而治之,将大问题分解为多个小问题,将复杂问题分解为多个简单问题
抽象:
更高层次来讲,人们处理复杂性有一个通用的技术,即抽象。由于不能掌握全部的复杂对象,我们选择忽视它的非本质的细节,而去处理泛华和理想化的对象模型。
如下是从分解和抽象两个维度的代码实现版本(感受需求变化代码改动情况)
Shape1.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 left_up;
int width;
int height;
Rect(const Point& left_up, const int width, const int height) {
this->left_up = left_up;
this->width = width;
this->height = height;
}
};
// 变化
class Circle {
// ...
};
MainForm1.cpp :
#include "Sharpe1.h"
#include <vector>
using namespace std;
class MainForm : public Form {
private:
Point p1;
Point p2;
vector<Line> vc_line;
vector<Rect> vc_rect;
// 变化
vector<Circle> vc_circle;
public:
MainForm() {
// ...
}
protected:
virtual void OnMouseDown(const MouseEventArgs& e);
virtual void OnMouseUp(const MouseEventArgs& e);
virtual void OnPaint(const MouseEventArgs& 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);
vc_rect.push_back(line);
}
else if(rdoRect.Checked){
int width = abs(p2.x - p1.x);
int height = abs(p2.y - p2.y);
Rect rect(p1, width, height);
vc_rect.push_back(rect);
}
else if (rdoCircle.Checked) {
{
// 变化
}
// ...
this->Refresh();
Form::OnMouseUp(e);
}
void MainForm::OnPaint(const MouseEventArgs& e) {
// 针对直线
for (auto& iter_line : vc_line)
{
e.Graphics.DrawLine(Pens.Red,
iter_line.start.x,
iter_line.end.y,
iter_line.end.x,
iter_line.end.y);
}
// 针对矩形
for (auto& iter_rect : vc_rect)
{
e.Graphics.DrawRectangle(Pens.Red,
iter_rect.left_up,
iter_rect.width,
iter_rect.height);
}
// 变化
for (auto& iter_circle : vc_circle)
{
// ...
}
//...
Form::OnPaint(e);
}
Shape1.h和MainForm1.cpp是第一个版本(分解的实现),客户变化,需要实现一个圆形,可以查看代码中标记未变化的地方,是为了满足客户需求做的改动,可以看出由于需求的变化,Shape1.h和MainForm1.cpp代码都进行了修改。
Shape2.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;
}
virtual void Draw(const Graphics& g) {
g.DrawLine(Pens.Red,
start.x, start.y, end.x, end.y);
}
};
class Rect : public Shape{
public:
Point left_up;
int width;
int height;
Rect(const Point& left_up, const int width, const int height) {
this->left_up = left_up;
this->width = width;
this->height = height;
}
virtual void Draw(const Graphics& g) {
e.Graphics.DrawRectangle(Pens.Red,
left_up,
width,
height);
}
};
// 变化
class Cicle : public Shape {
public:
virtual void Draw(const Graphics& g) {
e.Graphics.DrawCicle(...);
}
};
MainForm2.cpp:
#include "Shape2.h"
#include <vector>
using namespace std;
class MainForm : public Form {
private:
Point p1;
Point p2;
vector<Shape*> vc_shape;
public:
MainForm() {
// ...
}
protected:
virtual void OnMouseDown(const MouseEventArgs& e);
virtual void OnMouseUp(const MouseEventArgs& e);
virtual void OnPaint(const MouseEventArgs& 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){
vc_shape.push_back(new Line(p1, p2));
}
else if(rdoRect.Checked){
int width = abs(p2.x - p1.x);
int height = abs(p2.y - p2.y);
vc_shape.push_back(new Rect(p1, width, height));
}
else if(...)
{
// 变化
vc_shape.push_back(new Cicle());
}
// ...
Form::OnMouseUp(e);
}
void MainForm::OnPaint(const MouseEventArgs& e) {
// 针对所有形状
for (auto& iter_shape : vc_shape)
{
iter_shape->Draw(g); // 多态调用,各负其责
}
//...
Form::OnPaint(e);
}
Shape2.h和MainForm2.cpp是第二个版本(抽象的实现),客户变化,需要实现一个圆形,需要增加一个Cicle的类,MainForm2中创建Cicle对象,只需要改动这两处,可以看出第二个版本由于第一个版本。
什么是好的软件设计?软件设计的金科玉律:复用!