当前位置: 首页 > article >正文

理解为什么要有C++设计模式

什么时设计模式?

每一个模式描述了一个在我们周围不断重复的问题以及该问题的解决方案的核心,这样,就能一次有一次地使用该方案,而不必做重复劳动。

如何解决复杂性?

分解:人们面对复杂性有一个常见的做法:即分而治之,将大问题分解为多个小问题,将复杂问题分解为多个简单问题。

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

比如我们目前有这样的一个绘画类 Shape1.h

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{


};

主函数类 MainForm1.cpp

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 (...){
		//...
		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);
}

细心阅读上方的代码,我们发现,如果再次添加一种绘制方法,我们需要添加的操作分为了这几步:

  1. 在绘画类里面添加绘画方法;
  2. 在主函数类来进行判断他是什么绘制方法;
  3. 进行绘画。

但是我们通过C++的特性多态来进行操作的话,我们的操作步骤和代码量会明显的减少;如下所示:

绘画类 Shape1.h

lass 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 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,
			...);
	}

};

主函数类 MainForm1.cpp

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

从以上代码来看,明显代码量得到了优化,并且代码得到了复用
设计模式的存在其实就是做到让跟多复杂的代码,得到抽象处理,并得到代码复用。


http://www.kler.cn/a/381678.html

相关文章:

  • 探索AI代理在《我的世界》中的奇妙之旅:代理IP的角色与影响
  • 知乎 PB 级别 TiDB 数据库集群管控实践
  • 苏黎世联邦理工学院与加州大学伯克利分校推出MaxInfoRL:平衡内在与外在探索的全新强化学习框架
  • SSD目标检测算法
  • Java内存区域进一步详解
  • 【工作流】工作顺序
  • 移植 AWTK 到 纯血鸿蒙 (HarmonyOS NEXT) 系统 (9) - 编译现有的AWTK应用程序
  • wps表格数据竖排变成横排方法
  • qt QDropEvent详解
  • 【JavaEE初阶 — 多线程】Thread的常见构造方法&属性
  • AI教育革命:辅导孩子的新神器,你用对了吗?‍
  • 【Wi-Fi】802.11n Vs 802.11ac 整理
  • 大屏可视化:舞动数据与美观的“设计秘籍”
  • 使用 JPA 的 `save()` 方法更新数据库中的数据
  • 【数据湖及大数据方案】数据湖建设方案|数据源|数据流|元数据|数据仓库|指标池|数据清洗
  • 【VScode】C/C++多文件夹下、多文件引用、分别编译——仅一个设置【适合新人入手】
  • Python - PDF 分割成单页、PDF 转图片(PNG)
  • Ubuntu 安装CUDA, cuDNN, TensorRT(草稿)
  • 【LeetCode】【算法】236. 二叉树最近公共祖先
  • 消息队列面试——打破沙锅问到底
  • 【系统架构设计师】论文:论基于 ABSD 的软件开发
  • Elasticsearch实战应用:构建高效的全文搜索引擎
  • 跨平台使用高德地图服务
  • C# Modbus RTU通讯回顾
  • Rust常用数据结构教程 序列
  • [SDX35]SDX35 dtsi配置GPIO_108不生效问题分析及解决方案