第六篇、创建型设计模式——建造者(Builder)模式/生成器模式

建造者(Builder)模式又可以称为生成器模式,它是将一个复杂对象的构建与它的表示进行分离,使得同样的构建过程可以创建不同的表示。

那么,怎么理解这句话呢,其实说白了就是:当我们需要创建一个比较复杂的对象,并且,这个对象的创建过程比较稳定,那么,我们只需要通过指定这个对象的类型与内容,就可以一步一步的创建出这个复杂的对象,而无需知道这个对象内部的具体组装细节。


我们还是通过举例来进行描述。

大家都在外面吃过饭,相信都会遇到这样的情况,同样的一份木须肉,我们去不同的店,有的好吃,有的难吃。我们去麦当劳吃巨无霸汉堡,无论去那个店,味道基本一样。这是因为什么呢。用我们前面说过的一个原则解释,就是依赖倒转原则。就麦当劳而言,其对巨无霸汉堡的制作抽象出了一套流程,不管是哪个店,都要按照这个流程进行加工,其加工细节有具体的操作人员进行把控。然而作为木须肉,每家店都有自己的做法,缺少一套标准的制作流程,因此有些店做的好吃,有些店做的难吃。

麦当劳制作汉堡的过程,可以看做是建造者模式的一种体现:

1、首先,麦当劳有一款产品是汉堡

public class Hamburgers {
	private List<String> parts = new ArrayList<>();

	public void addPart(String part) {
		parts.add(part);
	}

	public void show() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("汉堡组成材料有");
		for (String p : parts) {
			buffer.append("/" + p);
		}
		System.out.println(buffer.toString());
	}

}
它有着自己的组成原料parts。

2、麦当劳为了将汉堡做的好吃,抽象出了一套成功的标准制作流程:

public abstract class Builder {
	public abstract void buildPartA();
	public abstract void buildPartB();
	public abstract void buildPartC();
	public abstract void buildPartD();
	public abstract Hamburgers getResult();
}
这套流程需要ABCD四步加工组装,从而获得成熟产品(getResult)。

3、具体的加工细节有专门的人负责(具体的创建者类):

public class HamburgersBuilder extends Builder {
	Hamburgers hamburgers = new Hamburgers();

	@Override
	public void buildPartA() {
		System.out.println("准备两个面包片");
		hamburgers.addPart("两个面包片");
	}

	@Override
	public void buildPartB() {
		System.out.println("在面包片中间放上肉片");
		hamburgers.addPart("肉片");
	}

	@Override
	public void buildPartC() {
		System.out.println("在肉片上放上蔬菜");
		hamburgers.addPart("蔬菜");
	}

	@Override
	public void buildPartD() {
		System.out.println("在蔬菜上涂抹上酱料");
		hamburgers.addPart("酱料");

	}

	@Override
	public Hamburgers getResult() {
		return hamburgers;
	}
}
4、还有一个指挥者在旁指挥,帮助产品顺利的制作成功:
public class Director {
	public void construct(Builder builder){
		builder.buildPartA();
		builder.buildPartB();
		builder.buildPartC();
		builder.buildPartD();
	}
}
指挥者要求,制作过程必须按照ABCD的顺序进行加工。

5、当客户需要汉堡时:

 Director director = new Director(); //找到指挥者
		 Builder hbgBuilder = new HamburgersBuilder(); //找到汉堡细节加工者
		
		 director.construct(hbgBuilder); //指挥者指挥汉堡加工者进行加工
		 Hamburgers hamburgers = hbgBuilder.getResult(); //获得汉堡
		 hamburgers.show();


这就是建造者模式的构架方式,大家可能没发现这个模式有什么优势,感觉绕来绕去的,还没有直接创建来得简单。

其实不然,首先,这种面向接口的编写方式,排除了可能因为失误所造成的产品残缺的问题,比如少加了调料,导致汉堡变难吃了。因为有抽象接口的约束,是加工人员知道,哪些步骤是必不可少的,避免了步骤遗漏。

然后呢,它的好处就是隐藏了产品的组装过程,使得客户无需知道其制作流程就可得到想要的产品。当需要添加新的同类产品,只需要再定义一个具体建造者就可以了。例如添加麦辣鸡腿汉堡,组装流程不变,材料及细节调整就好。

那么,什么时候我们要用到建造者模式呢?

当我们需要创建一些比较复杂的对象,这些对象的构建过程比较稳定,但是内部细节可能面临复杂的变化时,就要考虑运用此模式了。


建造者模式还有一个变种,相信大家也看到过,我们一起来看看。

大家都吃过砂锅米线吧,简单来说,一份砂锅米线必不可少的就是米线和一些基本配料,然后根据个人需要,可以选择性的添加配料,味道也可以选择原味的,微辣、中辣以及超辣。我们按照这个例子来运用一下变种Builder

首先,就是我们的米线类

public class MiXian {
	private List<String> parts;

	public MiXian(Builder builder) { //米线构造类听过接收Builder进行内容配置
		this.parts = builder.parts;
	}

	public void show() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("米线组成材料有");
		for (String p : parts) {
			buffer.append("/" + p);
		}
		System.out.println(buffer.toString());
	}

	public static final class Builder {  //米线的静态内部类Builder
		List<String> parts = new ArrayList<>();

		public Builder() {  //其构造器部分是砂锅米线必有的
			System.out.println("米线下锅 + 添加基本配料");
			parts.add("米线");
			parts.add("基本配料");
		}

		public Builder buildPartA() { //可选组成A
			System.out.println("另外添加配料一份");
			parts.add("额外配料");
			return this;
		}

		public Builder buildPartB() { //可选组成B
			System.out.println("不放辣椒——做成原味");
			return this;
		}

		public Builder buildPartC() { //可选组成C
			System.out.println("放少量辣椒——做成微辣");
			parts.add("少量辣椒");
			return this;
		}

		public Builder buildPartD() { //可选组成D
			System.out.println("放中量辣椒——做成中辣");
			parts.add("中量辣椒");
			return this;
		}

		public Builder buildPartE() { //可选组成E
			System.out.println("放大量辣椒——做成超辣");
			parts.add("大量辣椒");
			return this;
		}

		public MiXian build() {
			return new MiXian(this);
		}
	}
}
然后我们在客户端调用时,可以这样写:

MiXian miXian = new MiXian.Builder().buildPartA().buildPartC().build();
miXian.show();

是不是很熟悉的写法,一个方法链,其中的buildPartA、B、C、D、E都是可以根据个人需要进行选择性组装,从而获得拥有各自特点的产品对象。做Android开发的小伙伴会发现,其在Android中的应用比较广泛,比如AlertDialog:

new AlertDialog.Builder(this)
            .setTitle("提示")
            .setMessage("XXXXXXXXXXX")
            .setIcon(R.drawable.XX)
            .setCancelable(true)
            .setOnCancelListener(new DialogInterface.OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {
                    //...
                }
            })
            .show();

是不是用的很多!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值