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

原创 2015年07月07日 17:33:51

         概念

        建造者模式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、当构造过程必须允许被构造的对象有不同表示时。

    优点

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


版权声明:本文为博主原创文章,未经博主允许不得转载。

《小老爷们那点事儿》终极整理贴 (已完结)

《小老爷们那点事儿》终极整理贴  (已完结) 以下是分帖链接地址 小老爷们那点事儿整理帖之一 http://www.tulaoya.cn/bbs/read.php?tid=4 小老爷们那点事儿整理帖之...
  • metababy
  • metababy
  • 2007年08月24日 13:32
  • 18461

设计模式:建造者模式(Builder)

建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。  建造者模式通常包括下几个角色: 1. builder(抽象建造者):给出一个抽象结论,以规范产品对象的...
  • u013256816
  • u013256816
  • 2016年03月25日 11:18
  • 2062

设计模式——建造者

最近的心得,我发现学一门设计模式,不管你是否能立刻理解它,第一最要紧的是要记住两个东西。1、它是属于什么范畴的设计模式。2、记住UML图。这两个是打开这个设计模式之门的金钥匙!为什么这么讲?因为刚刚学...
  • hello_haozi
  • hello_haozi
  • 2014年08月25日 14:17
  • 16208

三分钟理解“建造者模式”——设计模式轻松掌握

“建造者模式”生活中的例子: 肯德基做汉堡的过程都是有严格的规范的,不管是麦香鸡腿堡还是新奥尔良烤鸡腿堡,他们的制作步骤都是有严格规定,做汉堡的人既不能多做一步,也不能少做一步。对于不同的汉堡来说,虽...
  • u010425776
  • u010425776
  • 2015年08月30日 14:07
  • 1238

Java程序员,上班那点事儿

清华大学出版社《Java程序员,上班那点事儿》作者:钟声 章节:1.1小节      我们刚刚进入本书的正题就拿出一个俗不可耐“钱”字来和大家大谈特谈,未免不雅。但是,我还是要在一开始就要说这个问题,...
  • jxf111348
  • jxf111348
  • 2009年08月18日 20:01
  • 427

【java设计模式】之 建造者(Builder)模式

我们还是举上一节的例子:生产汽车。上一节我们通过模板方法模式控制汽车跑起来的动作,那么需求是无止境的,现在如果老板又增加了额外的需求:汽车启动、停止、鸣笛引擎声都由客户自己控制,他想要什么顺序就什么顺...
  • eson_15
  • eson_15
  • 2016年05月06日 08:59
  • 5031

IT外企那点儿事完整版

第一章:外企也就那么回儿事 (http://blog.csdn.net/forfuture1978/article/details/5547537) 1.1 高薪 1.2 人性化 1.3 浮动工...
  • forfuture1978
  • forfuture1978
  • 2013年09月20日 13:55
  • 5072

大话设计模式—建造者模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。一个 Builder 类会一步一步构造最终...
  • lmb55
  • lmb55
  • 2016年03月27日 11:13
  • 1125

多线程那些事

多线程
  • qq_33344834
  • qq_33344834
  • 2016年07月28日 14:06
  • 203

从from or form说起,谈谈那些关于bug的事情

这篇博客,从我前段时间开发项目中出现的一个bug说起。一个把from写成form的bug说起                 一个不起眼的错误,可能是手误,可能是长期敲错导致坏习惯,也...
  • lfsf802
  • lfsf802
  • 2011年02月10日 08:40
  • 5855
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式那点事--建造者模式
举报原因:
原因补充:

(最多只允许输入30个字)