23种设计模式——Builder模式

本文深入探讨了建造者模式在处理复杂对象创建时的优势,特别是在对象内部表象与构建过程分离的情况下,如何有效管理对象的构建过程。通过实例分析,解释了如何利用构建者模式实现对象的灵活构建,以及它在确保对象完整性和构建过程可维护性方面的作用。

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

 
一、概述
在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法确相对稳定。如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?这就是要说的建造者模式。
 
建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。
 
对象性质的建造
有些情况下,一个对象会有一些重要的性质,在它们没有恰当的值之前,对象不能作为一个完整的产品使用。比如,一个电子邮件有发件人地址、收件人地址、主题、内容、附录等部分,而在最起码的收件人地址未被赋值之前,这个电子邮件不能发出。
有些情况下,一个对象的一些性质必须按照某个顺序赋值才有意义。在某个性质没有赋值之前,另一个性质则无法赋值。这些情况使得性质本身的建造涉及到复杂的商业逻辑。
这时候,此对象相当于一个有待建造的产品,而对象的这些性质相当于产品的零件,建造产品的过程就是组合零件的过程。由于组合零件的过程很复杂,因此,这些"零件"的组合过程往往被"外部化"到一个称作建造者的对象里,建造者返还给客户端的是一个全部零件都建造完毕的产品对象。
之所以使用"建造者"而没有用"生成器"就是因为用零件生产产品,"建造"更为合适,"创建"或"生成"不太恰当。
 
二、意图
将一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
 
三、Builder模式的结构
Builder:为创建Product对象的各个部件指定抽象接口。
ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并提供一个检索产品的接口。
Director:构造一个使用Builer接口的对象。
Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,以及将这些部件装配成最终产品的接口。
 
 
四、例子
下面我们举个例子来加深我们对Builder模式的理解。
比如我们要通过一个汽车加工厂,生产一辆汽车;汽车由车轮 方向盘 发动机还有各种小零件等等组成,它的基本组装步骤是:
- 生产车轮
- 生产方向盘
- 生产发动机
.................



通过上面的分析,我们知道,该范例满足Builder模式的应用场景所提到的条件:
- 对象的创建:我们需要创建汽车对象
- 创建的是一个复合对象:我们需要创建的汽车对象是具有车轮 方向盘 发动等复合属性的复合对象


下面我们用Builder设计模式来抽象以上组装过程:
- Client:买汽车的顾客。通过向Director申请,然后Director让Builder组装汽车

- Director:负责生产汽车的经理,或者销售人员
- Builder:汽车组装抽象类
- ConcreteBuilder:生产汽车的直接员工

Builder接口:

Java代码
public interface Builder {      
  //创建部件A  比如创建汽车车轮   
  void buildPartA();    
  //创建部件B 比如创建汽车方向盘   
  void buildPartB();    
  //创建部件C 比如创建汽车发动机   
  void buildPartC();    
  
  //返回最后组装成品结果 (返回最后装配好的汽车)   
  //成品的组装过程不在这里进行,而是转移到下面的Director类中进行.   
  //从而实现了解耦过程和部件   
  Product getResult();      
} 



用Director构建最后的复杂对象,而在上面Builder接口中封装的是如何创建一个个部件(复杂对象是由这些部件组成的),也就是说Director的内容是如何将部件最后组装成成品,即在director中就负责把零件拼装成成品,director封装了汽车生产的细节。

Java代码
public class Director {   
  private Builder builder;    
  public Director( Builder builder ) { //该构造子以Builder为参数   
    this.builder = builder;    
  }    
  // 将部件partA partB partC最后组成复杂对象   
  //这里是将车轮 方向盘和发动机组装成汽车的过程   
  public void construct() {    
    builder.buildPartA();   
    builder.buildPartB();   
    builder.buildPartC();    
  }    
}



Builder的具体实现ConcreteBuilder:
通过具体完成接口Builder来构建或装配产品的部件;
定义并明确它所要创建的是什么具体东西;
提供一个可以重新获取产品的接口:

Java代码
public class ConcreteBuilder implements Builder { 
  public void buildPartA() {
    //这里是具体如何构建partA的代码
  }; 
  public void buildPartB() { 
    //这里是具体如何构建partB的代码
  }; 
   public void buildPartC() { 
    //这里是具体如何构建partB的代码
  }; 
   public Product getResult() { 
    //返回最后组装成品结果
  };
}



复杂对象:产品Product:

Java代码
public interface Product 
{ 
    。。。。。
}



客户端调用:director负责发布命令,builder才负责真正的生产,所以向builder要产品而不是director

Java代码
//调用   
public class Client {   
    public static void main(String[] args) {   
        Builder builder = new ConcreteBuilder();   
        Director director = new Director( builder );    
        director.construct(); //builder负责真正的生产   
      Product product = builder.getResult();  //向builder要产品而不是向director要产品  
 }   
}

 

C++代码大致如下:

// 复杂对象部件接口
class CCarPart	{	};

// 这里有一个复杂对象类Product。它的构建需要PartA,PartB,PartC。
class CProduct	
{
public:
	CProduct(CCarPart* pCarPartA, CCarPart* pCarPartB, CCarPart* pCarPartC)	{	}
	~CProduct()	{	}
};

// 复杂对象的构建接口,产品生成器。
class CCarBuilder
{
public:
	virtual ~CCarBuilder()	{	}
	//创建部件A  比如创建汽车车轮 
	virtual void BuildPartA() = 0;
	//创建部件B 比如创建汽车方向盘 
	virtual void BuildPartB() = 0;
	//创建部件C 比如创建汽车发动机  
	virtual void BuildPartC() = 0;

	//返回最后组装成品结果 (返回最后装配好的汽车)      
	//成品的组装过程不在这里进行,而是转移到下面的Director类中进行.      
	//从而实现了解耦过程和部件
	virtual CProduct* GetProduct() = 0;
};

// 奥迪汽车,具体的产品生成器对象。
class CAudiBuilder : public CCarBuilder
{
public:
	CAudiBuilder()		{	}
	~CAudiBuilder()	{	}
public:
	virtual void BuildPartA()	{	printf("[CAudiBuilder] 创建奥迪汽车车轮 \n");	/*m_pPartA =*/ }
	virtual void BuildPartB()	{	printf("[CAudiBuilder] 创建奥迪汽车方向盘 \n");	/*m_pPartB =*/	}
	virtual void BuildPartC()	{	printf("[CAudiBuilder] 创建奥迪汽车发动机 \n");	/*m_pPartC =*/	}
	virtual CProduct* GetProduct()
	{
		printf("[CAudiBuilder] 组建奥迪汽车 \n");
		return new CProduct(m_pPartA, m_pPartB, m_pPartC);
	}
private:
	CCarPart* m_pPartA;
	CCarPart* m_pPartB;
	CCarPart* m_pPartC;
};

// 产品组装工厂
class CCarConstructFactory 
{
public:
	CCarConstructFactory(CCarBuilder* pBuilder)	: m_pBuilder(pBuilder)	{	}
	~CCarConstructFactory()	{	delete m_pBuilder;	m_pBuilder = NULL;	}

	// 在这里实现部件的组装及汽车的组装。
	void Construct()
	{
		m_pBuilder->BuildPartA();
		m_pBuilder->BuildPartB();
		m_pBuilder->BuildPartC();
	}
private:
	CCarBuilder* m_pBuilder;
};


C++ Demo测试代码

void BuilderDemo()
{
	// 建立产品生成器对象
	CCarBuilder* pBuilder = new CAudiBuilder();
	// 建立产品组装工厂,由工厂操作产品生成器进行组装
	CCarConstructFactory* pFactory = new CCarConstructFactory(pBuilder);
	// 开始组装。这里,改变工厂的组装过程,就可以组装成不同的产品。
	pFactory->Construct();
	// 组装完毕
	// 从产品生成器中得到产品
	CProduct* pProduct = pBuilder->GetProduct();
	// 释放资源
	delete pProduct;
	delete pFactory;
}
 

五、总结 

总之,Builder模式就是把复杂对象的创建和部件的创建分别开来,对象的创建用Director类来表示,而部件的创建用Builder类来表示.

适用性:

1、需要生成的产品对象有复杂的内部结构。
2、需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。

3、当复杂对象的创建应该独立于该对象的组成部分和装配方式时

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值