沉森心与思考同行

一点一滴,一滴一点。妈妈说过,要踏实做人,努力做事。

设计模式那点事--建造者模式

         概念

        建造者模式Builder),将一个复杂对象的创建与它的表示分离,使得同样的构建过程可以创建不同的表示。

        建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。我们只需指定需要建造的类型就可以得到它们,而具体建造的过程和细节就不需知道了。

        例子

        一个鲜活简单的例子总能让人轻松地理解晦涩的概念。我们来看看一个关于构建汽车的建造者模式。

        我们知道,汽车一般由轮胎,引擎和车身组成。就像宝马(BMW),法拉利(Ferrali)和奔驰(Benz)三辆汽车,它们也是由这三种东西组成的,只不过构成模块价格不同。

        对于它们来说,虽然组成模块价格不同,但是构建汽车都包含这三种东西,是一种公共操作。于是,可以创建一个抽象父亲汽车构建类(CarBuilder),声明三个构建函数virtual void BuildWheel等的接口。然后创建三个具体汽车构建子类:BMWBuilder,FerraliBuilder和BenzBuilder,用于具体汽车的构建,并提供返回具体汽车产品对象的接口。它们分别继承于CarBuilder,每个子类实现父类模块的个性化构建。

        然后再定义一个构建汽车指导者CarDirector,用于控制汽车建造过程,隔离用户与建造过程的关联。最后定义一个产品类Product,用于显示最终的生成汽车产品。

       角色

       1、建造者(Builder):为创建一个产品对象的各个部件指定抽象接口,如CarBuilder

       2、具体建造者(ConcreteBuilder):实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,提供一个获取汽车成品对象的接口,如BMWBilder

       3、指示领导者(Director):构造一个使用Builder接口的对象,用于控制建造过程,隔离用户与建造过程的关联,如CarDirector。

       4、具体产品(Product):表示被构造的复杂对象,如BMW汽车。

       UML


   代码:

#pragma warning(disable : 4786)

#include <iostream>
#include <vector>
#include <string>

using namespace std;

//具体产品类
class Product
{
public:
	vector<string> st;
public:
	void AddParts(string sValue)
	{
		st.push_back(sValue);
	}
	
	void Show()
	{
		for (vector<string>::iterator stIter=st.begin(); stIter!=st.end(); stIter++)
		{
			cout<<*stIter<<endl;
		}
	}
};

//建造者类
class CarBuilder
{
public:
	virtual void BuildWheel()
	{
		cout<<"CarBuilder:bulid wheel."<<endl; 
	}

	virtual void BuildEngine()
	{
		cout<<"CarBuilder:bulid engine."<<endl; 
	}

	virtual void BuildBody()
	{
		cout<<"CarBuilder:bulid body."<<endl; 
	}
};

//具体builder类,用于建造出具体产品
//实现CarBuilder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并 提供一个检索产品的接口
class BMWBuilder:public CarBuilder
{
public:
	Product product;
public:
	void BuildWheel()
	{
		product.AddParts("BMW:bulid wheel.");
	}
	
	void BuildEngine()
	{
		product.AddParts("BMW:bulid engine.");
	}
	
	void BuildBody()
	{
		product.AddParts("BMW:bulid body.");
	}
	
	Product GetProduct()
	{
		return product;
	}
};

class FerraliBuilder:public CarBuilder
{
public:
	Product product;
public:
	void BuildWheel()
	{
		product.AddParts("Ferrali:bulid wheel.");
	}
	
	void BuildEngine()
	{
		product.AddParts("Ferrali:bulid engine.");
	}
	
	void BuildBody()
	{
		product.AddParts("Ferrali:bulid body.");
	}
	
	Product GetProduct()
	{
		return product;
	}
};

class BenzBuilder:public CarBuilder
{
public:
	Product product;
public:
	void BuildWheel()
	{
		product.AddParts("Benz:bulid wheel.");
	}
	
	void BuildEngine()
	{
		product.AddParts("Benz:bulid engine.");
	}
	
	void BuildBody()
	{
		product.AddParts("Benz:bulid body.");
	}

	Product GetProduct()
	{
		return product;
	}
};

//指挥者,用于控制建造过程,隔离用户与建造过程的关联
class CarDirector
{
private:
	CarBuilder* cb;
public:
	CarDirector(CarBuilder* cb)
	{
		this->cb = cb;
	}

	~CarDirector()
	{
		if (cb!=NULL)
		{
			delete cb;
			cb = NULL;
		}
	}

	void CreateCar()
	{
		cb->BuildWheel();
		cb->BuildEngine();
		cb->BuildBody();
	}
};

int main()
{
	int iTag=0;
	Product product;
	
	cout<<"----建造者模式开始----"<<endl;
	cout<<"BMW:1,Ferrali:2,Benz:3"<<endl;
	cout<<"请输入您想要构建的汽车:";
	cin>>iTag;

	if(iTag==1)
	{
		BMWBuilder* bb= new BMWBuilder;
		CarDirector cd(bb);
		cd.CreateCar();
		product = bb->GetProduct();
		product.Show();
	}
	else if(iTag==2)
	{
		FerraliBuilder* fb= new FerraliBuilder;
		CarDirector cd(fb);
		cd.CreateCar();
		product = fb->GetProduct();
		product.Show();
	}
	else if(iTag==3)
	{
		BenzBuilder* bb= new BenzBuilder;
		CarDirector cd(bb);
		cd.CreateCar();
		product = bb->GetProduct();
		product.Show();
	}

	cout<<"----建造者模式结束----"<<endl;
	
	return 1;
}

    发散

     我们知道实现C++的多态有三种方法:函数重载,模板函数和虚函数。虚函数实现的多态称为动态多态,上面代码有以下特点:

     1、子类的对象转换给父类的对象如CarBuilder* cb= new BMWBuilder,我们称为向上转型。它是安全的,自动完成,并且会丢失子类型的信息;

     2、为了解决子类型信息丢失的问题(子类对象转换给父类),父类必须实现了一个虚函数BuildWheel

     3、子类有完全相同的BuildWheel函数,覆盖重写父类的虚函数BuildWheel,这样便能实现动态多态了(否则只能用指针或引用了)。

    应用场景

     1、当创建一些复杂对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建面临着复杂的变化;

     2、当构造过程必须允许被构造的对象有不同表示时。

    优点

    使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了,降低耦合性。


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oceanlucy/article/details/46792075
个人分类: 架构设计
想对作者说点什么? 我来说一句

软件秘笈:设计模式那点

2016年11月26日 91.54MB 下载

软件秘笈:设计模式那点事 下载

2016年12月03日 91.03MB 下载

设计模式笔记

2013年10月21日 44KB 下载

软件秘籍 设计模式那点

2017年08月09日 11.05MB 下载

设计模式那点事(光盘).zip

2013年01月26日 13.39MB 下载

设计模式源码

2013年11月28日 720KB 下载

设计模式那点

2013年01月17日 11.05MB 下载

软件秘籍示例代码

2017年08月09日 1.67MB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭