第十三章--好菜每回味不同-建造者模式(读书笔记)

本文探讨了建造者模式在复杂对象构建中的应用,通过实例展示了如何使用该模式来避免代码冗余,提高代码复用性和维护性。文中详细介绍了建造者模式的基本概念、实现步骤,并通过对比传统方式,阐述了其带来的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先看看下面的代码,是否可以发现有什么不好的地方?是的在没有建造者模式的代码中,很容易遗漏某些部分。

Main函数:

#include <QApplication>
#include "Mainimpl.h"

int main(int argc, char *argv[])
{
	QApplication app(argc, argv);
	Mainimpl* pMainWindow = new Mainimpl();
	pMainWindow->show();
	return app.exec();
 }
#pragma once
#include <QDialog>
#include <QPen>
#include <QColor>
#include <QPainter>

class Mainimpl :
	public QDialog
{
public:
	void paintEvent(QPaintEvent*)
	{
		QPen pen;
		pen.setWidth(10);
		pen.setStyle(Qt::SolidLine);
		QColor color(100,100,100);
		pen.setColor(color);

		QPainter paint(this);
		paint.setPen(pen);
		//画身体的各个部分
		paint.drawEllipse(50,20,30,30);
		paint.drawRect(60,50,10,50);
		paint.drawLine(60,50,40,100);
		paint.drawLine(70,50,90,100);
		paint.drawLine(60,100,45,150);
		paint.drawLine(70,100,85,150);
	};
};

1.中式的快餐为什么每回味不同?这是由于我们要吃的菜都依赖于厨师。其实根据依赖倒转原则,抽象不应该依赖细节,细节应该依赖于抽象。肯德基麦当劳的工作流程就是一种抽象的流程,具体放什么配料烤多长时间等细节依赖于这个抽象。
2.建造者模式(Builder)将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示。
3.如果我们用了建造者模式,那么用户就只需指定需要建造的类型就可以得到他们,而具体建造的过程和细节就不需知道了。
4.在构建小人的时候,要构建头,身体,左手,右手,左脚,右脚。为了不忘记其中的每一步,应该建一个抽象类,在这个抽象类中,分别加入构建头,身体,左手,右手,左脚,右脚的抽象函数。这样就不会忘记或者少构建一个了。
5.建造者模式中一个很重要的类:指挥者(Director),用它来控制建造过程,也用它来隔离用户与建造过程的关联。

PersonBuilder.h:有了建造者模式以后,建造头,手,身体等等都可以抽象化了

#pragma once
#include <QWidget>
#include <QPen>
#include <QPainter>

//建造抽象者
class PersonBuilder
{
public:
	virtual void BuildHead(QPainter& painter) = 0;
	virtual void BuildBody(QPainter& painter) = 0;
	virtual void BuildArmLeft(QPainter& painter) = 0;
	virtual void BuildArmRight(QPainter& painter) = 0;
	virtual void BuildLegLeft(QPainter& painter) = 0;
	virtual void BuildLegRight(QPainter& painter) = 0;

	virtual ~PersonBuilder(void){};
};

//瘦子的建造者
class PersonThinBuilder :public PersonBuilder
{
public:
	void BuildHead(QPainter& painter)
	{
		painter.drawEllipse(50,20,30,30);
	};
	void BuildBody(QPainter& painter)
	{
		painter.drawRect(60,50,10,50);
	};
	void BuildArmLeft(QPainter& painter)
	{
		painter.drawLine(60,50,40,100);
	};
	void BuildArmRight(QPainter& painter)
	{
		painter.drawLine(70,50,90,100);
	};
	void BuildLegLeft(QPainter& painter)
	{
		painter.drawLine(60,100,45,150);
	};
	void BuildLegRight(QPainter& painter)
	{
		painter.drawLine(70,100,85,150);
	};
};


//胖子的建造者
class PersonFatBuilder :public PersonBuilder
{
public:
	void BuildHead(QPainter& painter)
	{
		painter.drawEllipse(50,20,30,30);
	};
	void BuildBody(QPainter& painter)
	{
		painter.drawRect(45,50,40,50);
	};
	void BuildArmLeft(QPainter& painter)
	{
		painter.drawLine(50,50,30,100);
	};
	void BuildArmRight(QPainter& painter)
	{
		painter.drawLine(80,50,100,100);
	};
	void BuildLegLeft(QPainter& painter)
	{
		painter.drawLine(60,100,45,150);
	};
	void BuildLegRight(QPainter& painter)
	{
		painter.drawLine(70,100,85,150);
	};
};

//指挥者
class PersonDirector :public QWidget
{
public:
	PersonDirector(PersonBuilder* p)
	{
		m_pPersonBuilder = p;
	};
	~PersonDirector()
	{
		if (m_pPersonBuilder != NULL)
		{
			delete m_pPersonBuilder;
			m_pPersonBuilder = NULL;
		}
	};
	void CreatePerson(void)
	{
		this->show();
	};

	void paintEvent(QPaintEvent*)
	{
		QPen pen;
		pen.setWidth(10);
		pen.setStyle(Qt::SolidLine);

		QPainter paint(this);
		paint.setPen(pen);
		m_pPersonBuilder->BuildHead(paint);
		m_pPersonBuilder->BuildBody(paint);
		m_pPersonBuilder->BuildArmLeft(paint);
		m_pPersonBuilder->BuildArmRight(paint);
		m_pPersonBuilder->BuildLegLeft(paint);
		m_pPersonBuilder->BuildLegRight(paint);
	};
private:
	PersonBuilder* m_pPersonBuilder;
};
#include <QApplication>
#include "PersonBuilder.h"

int _tmain(int argc, _TCHAR* argv[])
{
	QApplication app(argc, argv);
	PersonBuilder* thinPerson = new PersonThinBuilder();
	PersonDirector director(thinPerson);
	director.CreatePerson();

	PersonBuilder* fatPerson = new PersonFatBuilder();
	PersonDirector director2(fatPerson);
	director2.CreatePerson();
	return app.exec();
}

代码相关联的图如下图表示:


6.建造者模式主要用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。
7.建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式时适用的模式。
8.如果大排档作炒面的老板知道建造者模式,它就明白,盐是一定要放的,不然编译就通不过。
下面是净化版的建造者模式,建造的各个部分用了向量结构来表示。首先是建造的实现者:

#pragma once
#include <vector>
#include <string>
#include <iostream>

class Product
{
public:
	~Product()
	{
		m_parts.clear();
	};
	void Add(std::string myPart)
	{
		m_parts.push_back(myPart);
	};
	void Show()
	{
		std::cout << "开始表示." << std::endl;
		if (!m_parts.empty())
		{
			std::vector<std::string>::iterator iter = m_parts.begin();
			while (iter != m_parts.end())
			{
				std::cout << (*iter) << std::endl;
				++iter;
			}
		}
	};
private:
	std::vector<std::string> m_parts;
};

接来下是建造类。Builder.h:

#pragma once
#include "Product.h"

class Builder
{
public:
	virtual void BuilderPartA(void) = 0;
	virtual void BuilderPartB(void) = 0;
	virtual Product* GetResult(void) = 0;
};

class ConcreteBuilder1 : public Builder
{
public:
	ConcreteBuilder1()
	{
		m_pProduct = new Product();
	}
	~ConcreteBuilder1()
	{
		if (m_pProduct != NULL)
		{
			delete m_pProduct;
			m_pProduct = NULL;
		}
	}
	void BuilderPartA(void)
	{
		m_pProduct->Add("PartA");
	};
	void BuilderPartB(void)
	{
		m_pProduct->Add("PartB");
	};
	Product* GetResult(void)
	{
		return m_pProduct;
	};
private:
	Product* m_pProduct;
};


class ConcreteBuilder2 : public Builder
{
public:
	ConcreteBuilder2()
	{
		m_pProduct = new Product();
	}
	~ConcreteBuilder2()
	{
		if (m_pProduct != NULL)
		{
			delete m_pProduct;
			m_pProduct = NULL;
		}
	}
	void BuilderPartA(void)
	{
		m_pProduct->Add("PartX");
	};
	void BuilderPartB(void)
	{
		m_pProduct->Add("PartY");
	};
	Product* GetResult(void)
	{
		return m_pProduct;
	};
private:
	Product* m_pProduct;
};
#pragma once
#include "Builder.h"

class Director
{
public:
	void Construct(Builder* builder)
	{
		builder->BuilderPartA();
		builder->BuilderPartB();
	};
};
//这里是指挥者,它对细节已经知道的很少了。



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的横打

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值