第六篇、创建型设计模式——建造者(Builder)模式/生成器模式
2017-03-07 15:57
615 查看
建造者(Builder)模式又可以称为生成器模式,它是将一个复杂对象的构建与它的表示进行分离,使得同样的构建过程可以创建不同的表示。
那么,怎么理解这句话呢,其实说白了就是:当我们需要创建一个比较复杂的对象,并且,这个对象的创建过程比较稳定,那么,我们只需要通过指定这个对象的类型与内容,就可以一步一步的创建出这个复杂的对象,而无需知道这个对象内部的具体组装细节。
我们还是通过举例来进行描述。
大家都在外面吃过饭,相信都会遇到这样的情况,同样的一份木须肉,我们去不同的店,有的好吃,有的难吃。我们去麦当劳吃巨无霸汉堡,无论去那个店,味道基本一样。这是因为什么呢。用我们前面说过的一个原则解释,就是依赖倒转原则。就麦当劳而言,其对巨无霸汉堡的制作抽象出了一套流程,不管是哪个店,都要按照这个流程进行加工,其加工细节有具体的操作人员进行把控。然而作为木须肉,每家店都有自己的做法,缺少一套标准的制作流程,因此有些店做的好吃,有些店做的难吃。
麦当劳制作汉堡的过程,可以看做是建造者模式的一种体现:
1、首先,麦当劳有一款产品是汉堡
2、麦当劳为了将汉堡做的好吃,抽象出了一套成功的标准制作流程:
3、具体的加工细节有专门的人负责(具体的创建者类):
5、当客户需要汉堡时:
这就是建造者模式的构架方式,大家可能没发现这个模式有什么优势,感觉绕来绕去的,还没有直接创建来得简单。
其实不然,首先,这种面向接口的编写方式,排除了可能因为失误所造成的产品残缺的问题,比如少加了调料,导致汉堡变难吃了。因为有抽象接口的约束,是加工人员知道,哪些步骤是必不可少的,避免了步骤遗漏。
然后呢,它的好处就是隐藏了产品的组装过程,使得客户无需知道其制作流程就可得到想要的产品。当需要添加新的同类产品,只需要再定义一个具体建造者就可以了。例如添加麦辣鸡腿汉堡,组装流程不变,材料及细节调整就好。
那么,什么时候我们要用到建造者模式呢?
当我们需要创建一些比较复杂的对象,这些对象的构建过程比较稳定,但是内部细节可能面临复杂的变化时,就要考虑运用此模式了。
建造者模式还有一个变种,相信大家也看到过,我们一起来看看。
大家都吃过砂锅米线吧,简单来说,一份砂锅米线必不可少的就是米线和一些基本配料,然后根据个人需要,可以选择性的添加配料,味道也可以选择原味的,微辣、中辣以及超辣。我们按照这个例子来运用一下变种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();
是不是用的很多!
那么,怎么理解这句话呢,其实说白了就是:当我们需要创建一个比较复杂的对象,并且,这个对象的创建过程比较稳定,那么,我们只需要通过指定这个对象的类型与内容,就可以一步一步的创建出这个复杂的对象,而无需知道这个对象内部的具体组装细节。
我们还是通过举例来进行描述。
大家都在外面吃过饭,相信都会遇到这样的情况,同样的一份木须肉,我们去不同的店,有的好吃,有的难吃。我们去麦当劳吃巨无霸汉堡,无论去那个店,味道基本一样。这是因为什么呢。用我们前面说过的一个原则解释,就是依赖倒转原则。就麦当劳而言,其对巨无霸汉堡的制作抽象出了一套流程,不管是哪个店,都要按照这个流程进行加工,其加工细节有具体的操作人员进行把控。然而作为木须肉,每家店都有自己的做法,缺少一套标准的制作流程,因此有些店做的好吃,有些店做的难吃。
麦当劳制作汉堡的过程,可以看做是建造者模式的一种体现:
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();
是不是用的很多!
相关文章推荐
- 设计模式03: Builder 生成器模式(创建型模式)
- [设计模式-创建型]建造者(Builder)
- C#面向对象设计模式学习笔记(3) - Builder 生成器模式(创建型模式)
- C#设计模式之五建造者模式(Builder)【创建型】
- (六)二十三中设计模式之我见------------建造者模式或生成器模式(Builder Pattern)
- 设计模式(4)-创建型-建造者(Builder)(个人笔记)
- 跟着实例学习设计模式(6)-生成器模式builder(创建型)
- PHP设计模式:创建型之建造者(Builder)
- 设计模式(4)建造者模式/生成器模式(Builder)
- Java设计模式(5)——创建型模式之建造者模式(Builder)
- 设计模式之建造者模式Builder(创建型)
- C++设计模式 -> 创建型 -> 建造者(Builder)
- [设计模式-创建型]建造者(Builder)
- 设计模式(三):建造者模式Builder(创建型模式)
- (创建型模式)Builder 建造者模式
- .NET设计模式(4):建造者模式(Builder Pattern)
- .NET设计模式(4):建造者模式(Builder Pattern)
- .NET设计模式(4):建造者模式(Builder Pattern)
- .NET设计模式(4):建造者模式(Builder Pattern)
- 设计模式---建造者(Builder)模式,有关系图