建造者模式简介

15 篇文章 2 订阅
1 篇文章 0 订阅

建造者模式听起来有点高大上, 也是程序猿之间常常提起的模式之一.

其实它有1个前提跟模板方法模式(Template Method)有点类似, 就是建造这个过程可以分拆成若干个部分(步骤).

我们先看定义.


一, 建造者模式的定义

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


定义很简练啊.


关键词如下:

什么是 构建?

什么是 表示?

什么是 分离?


这里先简单解释一下:

构建:

        就是完成1件由若干步骤组成的过程.


表示:

       就是将对象表达出来(文字表达, 图形表达..等)


分离:

       就是代码写在不同的类中.


下面举几个例子详解.


二, 使用模板方法模式 实现 汽车制造的1个简单例子.

我们假设, suppose, 1辆汽车的制造过程只有3步:

1. 制造引擎.

2. 制造车身.

3. 制造论坛


现在要求做1个可以实现 制造Fort汽车 和 Benz汽车 的类设计.


我们以前讲过, 模板方法可以实现步骤分离.

那么先试着使用模板方法实现:


2.1 抽象类MakeCar

public abstract class MakeCar {
	private ArrayList<String> partList = new ArrayList<String>();
	ArrayList<String> getPartList(){
		return this.partList;
	}
	
	abstract void buildEngine();
	abstract void buildBody();
	abstract void buildwheels();
	
	public void build(){
		this.buildEngine();
		this.buildBody();
		this.buildwheels();
	}
	
	public void show(){
		System.out.println(this.getClass().getSimpleName() + ": " + this.getPartList());
	}
}

注意,

里面的 build() 相当于构建(由若干步骤组成)

里面的 show() 就相当于表示了.


2.2 类MakeFortCar

public class MakeFortCar extends MakeCar{

	@Override
	void buildEngine() {
		// TODO Auto-generated method stub
		this.getPartList().add("Fort-Engine");
	}

	@Override
	void buildBody() {
		// TODO Auto-generated method stub
		this.getPartList().add("Fort-Body");
	}

	@Override
	void buildwheels() {
		// TODO Auto-generated method stub
		this.getPartList().add("Fort-wheels");
	}
	
}

2.3 类MakeFortCar

public class MakeBenzCar extends MakeCar{

	@Override
	void buildEngine() {
		// TODO Auto-generated method stub
		this.getPartList().add("Benz-Engine");
	}

	@Override
	void buildBody() {
		// TODO Auto-generated method stub
		this.getPartList().add("Benz-Body");
	}

	@Override
	void buildwheels() {
		// TODO Auto-generated method stub
		this.getPartList().add("Benz-wheels");
	}
	
}


2.4 客户端代码:

	MakeCar mFort = new MakeFortCar();
		mFort.build();
		mFort.show();
		
		MakeCar mBenz = new MakeBenzCar();
		mBenz.build();
		mBenz.show();


这种写法的优点:

1.在客户端隐藏了构造过程的细节, 这个也是模板方法模式的优点.

2. 可以有多个子类继承同1个模板, 也就是同样可以实现一样可以实现 1个构建过程可以创建不同的表示.


然后看看这样的写法有什么缺点:


1. 看起来是汽车自己制造了自己, 没有1个建设者的角色存在. 无角色区别.

2. 构建方法build() 跟表示方法 show()写在同1个类. 没有分离


3. 若现实中构建方法build() , 也就是建造顺序一但修改, 若遵循封闭-开放 原则,则整套代码不适用了. 

    因为模板方法之所以叫做模板方法, 是因为模板本身是不改的, 一套类对应1个模板.


    而, 汽车生产中, 建造顺序往往会有变化, 甚至有额外的工序. 例如货车需要1个集装箱等.




三, 使用建造者模式实现上面的例子.


建设者模式的角色有3个.


1. 产品(product)       就是指建造的产品, 这个例子指的就是汽车. 它有方法可以表示自己.

2. 建设者(Builder)   整个模式的核心, 它负责怎样去实现产品中每个部分(零件)的制造.

3. 指挥者(Director)  相当于1个项目经理模式, 它指挥产品中每个部分的完成顺序.


从解释中大概已经估算出, 构建方法在指挥者里,  表示方法在产品里.


具体代码如下:


3.1 产品类CarProduct:

import java.util.ArrayList;
public class CarProduct {
	private ArrayList<String> partList = new ArrayList<String>();
	private String brandName;
	
	void addPart(String part){
		this.partList.add(part);
	}
	
	void setbrand(String name){
		this.brandName = name;
	}
	
	public void show(){
		System.out.println(this.brandName + ":" + partList);
	}
}

注意这里数组添加的部分是String格式, 实际项目中很可能是1个对象(零件类对象)

3.2 抽象建设者类CarBuilder

public abstract class CarBuilder {
	private CarProduct prod = new CarProduct();
	
	CarProduct getProd() {
		return prod;
	}
	
	void setProd(CarProduct prod) {
		this.prod = prod;
	}
	
	abstract void setBrand();
	abstract void buildEngine();
	abstract void buildBody();
	abstract void buildWheels();
}

3.3 FortCarBuilder

public class FortCarBuilder extends CarBuilder {

	@Override
	void setBrand() {
		// TODO Auto-generated method stub
		this.getProd().setbrand("Fort");
	}

	@Override
	void buildEngine() {
		// TODO Auto-generated method stub
		this.getProd().addPart("Fort-Engine");
	}

	@Override
	void buildBody() {
		// TODO Auto-generated method stub
		this.getProd().addPart("Fort-Body");
	}

	@Override
	void buildWheels() {
		// TODO Auto-generated method stub
		this.getProd().addPart("Fort-Wheels");
	}

}

3.4 BenzCarBuilder

public class BenzCarBuilder extends CarBuilder {

	@Override
	void setBrand() {
		// TODO Auto-generated method stub
		this.getProd().setbrand("Benz");
	}

	@Override
	void buildEngine() {
		// TODO Auto-generated method stub
		this.getProd().addPart("Benz-Engine");
	}

	@Override
	void buildBody() {
		// TODO Auto-generated method stub
		this.getProd().addPart("Benz-Body");
	}

	@Override
	void buildWheels() {
		// TODO Auto-generated method stub
		this.getProd().addPart("Benz-Wheels");
	}

}

3.5 指挥者CarDirector()

public class CarDirector {
	public void construct(CarBuilder cb){
		cb.setBrand();
		cb.buildEngine();
		cb.buildBody();
		cb.buildWheels();
	}
}


3.6 客户端代码:

CarProduct prod;
		CarDirector cd = new CarDirector();
		
		CarBuilder cb = new FortCarBuilder();
		cd.construct(cb);
		prod = cb.getProd();
		prod.show();
		
		cb = new BenzCarBuilder();
		cd.construct(cb);
		prod = cb.getProd();
		prod.show();


3. 7 UML







3. 8 这样用建造者模式实现的好处

1. 从客户端代码, 出现了指挥者, 建造者, 产品3种角色, 就如指挥者指挥建造者建造了产品一样.   跟业务逻辑结合得好

    当然, 这个例子1个建造者(builder)只生产1个产品.


2. 构建过程卸载指挥者类里,  表示方法写在产品类里,  也就是构建过程与表示分离.


3. 同1个指挥者实现了两种产品(Fort Benz)的生产和表示, 也就是定义中的1个构建过程可以实现不同的表示.


4. 当某个产品的制造顺序改变是, 只需要新增1个指挥者子类,  让新的指挥者去指挥建设者生产就可以了. 其他类不受影响.

     也就是说这种改动符合封闭 - 开放原则.



































































  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

nvd11

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

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

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

打赏作者

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

抵扣说明:

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

余额充值