设计模式第一讲--设计模式简介
1. 课程目标
(1)理解松耦合设计思想
(2)掌握面向对象设计原则
(3)掌握重构技法改善设计
(4)掌握GOF核心设计模式
2. 《设计模式:可复用面向对象软件的基础》
可复用是设计模式的目标,面向对象是方法。通常说的设计模式默认为面向对象的设计模式,但这并不意味着设计模式就等于面向对象的设计模式。
3. 底层思维:向下,如何把握机器底层从围观理解对象构造
语言构造、编译转换、内存模型、运行时机制。
抽象思维:向上,如何将我们的周围世界抽象为程序代码
面向对象、组件封装、设计模式、架构模式。
深入理解面向对象:
向下:深入理解三大面向对象机制
封装:隐藏内部实现
继承:复用现有代码
多态:修改对象行为
向上:深刻把握面向对象机制所带来的抽象意义,理解如何使用这些机制来表达现实世界,掌握什么是“好的面向对象设计”。
4. 如何解决复杂性?
(1)分解 分而治之,将大问题分解成多个小问题,将复杂问题分解为多个简单问题。
(2)抽象 更高层次来讲,人们处理复杂性有一个通用的技术,即抽象。由于不能掌握全部的复杂对象,我们选择忽视它的非本质细节,而去处理泛化和理想化了的对象模型。
5.假设在一个界面上可以绘制线条和矩形
(1)用分解的思路实现,伪代码如下:
shape.h文件内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #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 leftUp; int width; int height; Rect( const Point& leftUP, int width, int height) { this ->leftUp = leftUP; this ->height = height; this ->width = width; } }; |
每一个形状对应各自的类。
MainForm.cpp中的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #include "Shape.h" #include<vector> using namespace std; class MainForm : public Form { private : Point p1; //表示鼠标按下和抬起的点 Point p2; vector<Line> lineVector; vector<Rect> rectVector; 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) { 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); } //... this ->Refresh(); //系统会调用OnPaint 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); } //... Form::OnPaint(e); } |
现在有一个需求,要求可以再界面上绘制圆形。
为了实现这个目标,书写的代码如下:
shape.h文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | #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 leftUp; int width; int height; Rect( const Point& leftUP, int width, int height) { this ->leftUp = leftUP; this ->height = height; this ->width = width; } }; //新加代码 class Circle { public : Point Center; int Radius; Circle( const Point& center, int radius) { this ->Center = center; this ->Radius = radius; } }; |
MainForm.cpp文件内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | #include "Shape.h" #include<vector> using namespace std; 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; //... 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); } else if (rdoCircle.Checked) { Point center; center.x = (p1.x + p2.x) / 2; center.y = (p1.y + p2.y) / 2; int radius = sqrt ( pow ( abs (p1.x - p2.x), 2) + pow ( abs (p1.y - p2.y), 2)) / 2; Circle circle(center,radius); circleVector.push_back(circle); } //... this ->Refresh(); //系统会调用OnPaint 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, rectVector[i].Center, rectVector[i].Radius); } //... Form::OnPaint(e); } |
(2)抽象的思路实现界面上可以绘制直线和矩形的功能
Shape1.h文件内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #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 Graphic& 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); } }; |
创建名为Shape的基类,线条类和矩形类都继承Shape基类,其再各自的类中实现Draw方法。
MainForm1.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | #include "Shape1.h" #include<vector> 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 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)); } //... this ->Refresh(); //系统会调用OnPaint 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); } |
那这个时候,只需要再MainForm类中创建存储Shape*的vector数组就好,不必针对每一中类型创建vector了。
那现在我们有相同的需求,都是在界面上可以绘制圆形。对应修改的代码如下:
Shape1.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | #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 Graphic& 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 : Point Center; int Radius; Circle( const Point& center, int radius) { this ->Center = center; this ->Radius = radius; } // 实现自己的Draw,负责画自己 virtual void Draw( const Graphics & g) { g.DrawCircle(Pens.red, Center, Radius); } }; |
MainForm.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | #include "Shape1.h" #include<vector> 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 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 (rdoCircle.Checked) { Point center; center.x = (p1.x + p2.x) / 2; center.y = (p1.y + p2.y) / 2; int radius = sqrt ( pow ( abs (p1.x - p2.x), 2) + pow ( abs (p1.y - p2.y), 2)) / 2; shapeVector.push_back( new Circle(center, radius)); } //... this ->Refresh(); //系统会调用OnPaint 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); } |
可以看的出,对应相同的功能,面向对象的设计方式比分解的设计方式改动要少的多。
代码的复用性也好的多。
posted on 2021-11-25 08:36 xcxfury001 阅读(28) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用