赞
踩
整理自李建忠老师的《C++设计模式》视频教程
课程目标
“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”。——Christopher Alexander
从面向对象谈起
建筑商从来不会去想给一栋已建好的100层高的楼房底下再新修一个小地下室——这样做花费极大而且注定要失败。然而令人惊奇的是,软件系统的用户在要求作出类似改变时却不会仔细考虑,而且他们认为这只是需要简单编程的事。——Object-Oriented Analysis and Design with Applications(by Grady Booch)
分解
抽象
show me the code
// C++的一般设计原则
// 数据设置为private:
// 一个类放在一个文件中 …
// 为了演示的方便可能没有遵守这些规范
C++中所有的继承,推荐使用public继承,绝大多数都使用public继承
某些数据和接口需要给给子类使用,设置为protected
本类使用的数据和接口,设置为private
//-----------------------------------------------------------------// //点 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{ private: Point leftUp; int width; int height; public: Rect(const Point& leftUp, int width, int height){ this->leftUp = leftUp; this->width = width; this->height = height; } }; //增加 !!! //圆 class Circle{ }; //-----------------------------------------------------------------// //窗口类 表单类 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;//鼠标按下时取第一个点p1 //... Form::OnMouseDown(e); } void MainForm::OnMouseUp(const MouseEventArgs& e) //鼠标抬起 { p2.x = e.X; p2.y = e.Y;//鼠标抬起时取第二个点p1 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 (...){ //... circleVector.push_back(circle); } //刷新 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 (int i = 0; i < circleVector.size(); i++){ e.Graphics.DrawCircle(Pens.Red, circleVector[i]); } //... Form::OnPaint(e); }
//-----------------------------------------------------------------// class Shape{ public: virtual void Draw(const Graphics& g)=0; virtual ~Shape() { } }; class Point{ public: int x; int y; }; // C++中所有的继承,推荐使用public继承,绝大多数都使用public继承 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; } //实现自己的Draw,负责画自己 virtual void Draw(const Graphics& g){ g.DrawRectangle(Pens.Red, leftUp,width,height); } }; //当需求变更时,这种设计方法,几乎只有此处需要改变(增加) //也就是重用性得到了很高的提升,复用性高 //增加!!! class Circle : public Shape{ public: //实现自己的Draw,负责画自己 virtual void Draw(const Graphics& g){ g.DrawCircle(Pens.Red, ...); } }; //-----------------------------------------------------------------// 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 (...){ //... shapeVector.push_back(circle); } //... this->Refresh(); 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); }
什么是好的软件设计?软件设计的金科玉律:复用!
复用!
抽象是为了复用!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。