设计模式第一讲–设计模式简介(Lecture 1 on design patterns — Introduction to design patterns)

1. 课程目标

(1)理解松耦合设计思想

(2)掌握面向对象设计原则

(3)掌握重构技法改善设计

(4)掌握GOF核心设计模式

2. 《设计模式:可复用面向对象软件的基础》

可复用是设计模式的目标,面向对象是方法。通常说的设计模式默认为面向对象的设计模式,但这并不意味着设计模式就等于面向对象的设计模式。

3. 底层思维:向下,如何把握机器底层从围观理解对象构造

语言构造、编译转换、内存模型、运行时机制。

抽象思维:向上,如何将我们的周围世界抽象为程序代码

面向对象、组件封装、设计模式、架构模式。

深入理解面向对象:

向下:深入理解三大面向对象机制

封装:隐藏内部实现

继承:复用现有代码

多态:修改对象行为

向上:深刻把握面向对象机制所带来的抽象意义,理解如何使用这些机制来表达现实世界,掌握什么是“好的面向对象设计”。

4. 如何解决复杂性?

(1)分解 分而治之,将大问题分解成多个小问题,将复杂问题分解为多个简单问题。

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

5.假设在一个界面上可以绘制线条和矩形

(1)用分解的思路实现,伪代码如下:

shape.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 leftUp;
	int width;
	int height;

	Rect(const Point& leftUP, int width, int height)
	{
		this->leftUp = leftUP;
		this->height = height;
		this->width = width;
	}
};

  每一个形状对应各自的类。

MainForm.cpp中的内容

#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文件

#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文件内容

#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文件内容

#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

#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

#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

#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);
}  

可以看的出,对应相同的功能,面向对象的设计方式比分解的设计方式改动要少的多。

代码的复用性也好的多。

————————

one   Course objectives

(1) Understand loosely coupled design ideas

(2) Master object-oriented design principles

(3) Master reconstruction techniques to improve design

(4) Master GOF core design mode

two   Design patterns: the foundation of Reusable Object-Oriented Software

Reusability is the goal of design patterns, and object-oriented is the method. Generally speaking, the default design pattern is object-oriented design pattern, but this does not mean that design pattern is equal to object-oriented design pattern.

three   Bottom thinking: down, how to grasp the bottom of the machine and understand the object structure from the onlookers

Language construction, compilation and conversion, memory model, runtime mechanism.

Abstract thinking: upward, how to abstract the world around us into program code

Object oriented, component encapsulation, design pattern, architecture pattern.

Deep understanding of object orientation:

Downward: deeply understand the three object-oriented mechanisms

Encapsulation: hiding internal implementations

Inheritance: reusing existing code

Polymorphism: modifying object behavior

Upward: deeply grasp the abstract meaning brought by object-oriented mechanisms, understand how to use these mechanisms to express the real world, and master what is “good object-oriented design”.

four   How to solve complexity?

(1) Decompose divide and conquer, decompose large problems into multiple small problems, and decompose complex problems into multiple simple problems.

(2) At a higher level of abstraction, there is a general technology for people to deal with complexity, that is, abstraction. Because we can’t grasp all the complex objects, we choose to ignore its non essential details and deal with the generalized and idealized object model.

5. Suppose you can draw lines and rectangles on an interface

(1) The pseudo code is as follows:

Shape. H file content

#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;
	}
};

Each shape corresponds to its own class.

Contents in mainform.cpp

#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);
}

Now there is a requirement that circles can be drawn on the interface.

In order to achieve this goal, the written code is as follows:

Shape. H file

#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;
	}
};

Contents of mainform.cpp file

#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) Abstract ideas to achieve the function of drawing lines and rectangles on the interface

Shape1. H file content

#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);
	}
};

Create a base class named shape. The line class and rectangle class inherit the shape base class and implement the draw method in their respective classes.

MainForm1.cpp

#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);
}

At this time, you only need to create a vector array storing shape * in the MainForm class, instead of creating a vector for each type.

Now we have the same requirements. We can draw circles on the interface. The corresponding modified code is as follows:

Shape1.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;
	}

	//实现自己的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

#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);
}  

It can be seen that corresponding to the same function, the object-oriented design method changes much less than the decomposition design method.

Code reusability is much better.