Builder 模式
来源:互联网 发布:二阶矩阵特征值的求法 编辑:程序博客网 时间:2024/09/21 09:25
问题背景
你要建造一所房子。大兴土木当然应该用很多劳力,但是知识分子也是必要的——要不房子结构会出问题,或者很难看。你需要一个设计师,这个人呢,知道怎么建房子。这个人会告诉你,建房子啊,应该先从底下开始(神说地基已经打好了),你得先弄弄地板,再弄弄墙,再在墙上打几个洞,一些当窗户,弄个接地气的当门。
设计一
所以我们有了一个无脑的设计。
class House { private void buildFloor() { // } private void buildWall() { // } private void buildWindows() { // } private void buildDoor() { // } public House() { buildFloor(); buildWall(); buildWindows(); buildDoor(); }}
不过其实也不是非常无脑,起码你没把四个 build*
函数的东西一股脑都填到构造函数里。
设计一的问题
那么这个设计怎么样呢?直接看起来好像还好。
可是天要亡你。用户改需求啦!用户说,我有 100 套房子(壕),怎么能都建成一样的呢?我要这几套建成中式(China
)的,这几套建成罗马式(Rome
)的,那几套……
设计师一听就头大了,这样一想原来的设计的确有问题:它的扩展性太差。不能支持“房子”的多样性。
出现这种状况的原因是什么呢?我们看一看这个类有什么功能。第一、它建立了房子的各个部分;第二、它将各个部分组合起来。
如果是一个简单一点的类的话,这样写其实没有多大问题,类有几个部分的话自然就应该这么构造。可是房子这个类比较复杂,它的种类太多也就是第一个功能部分要求扩展性;同时又有比较固定的构成,有了地板、墙壁、门等的构造方法之后,不论他们是什么风格的,组合起来的逻辑都是一样的。
也就是说,房子这个类具有两个特性:
- 成分多样性高。
- 各个成分直接组成逻辑固定。
对应着两项特性,构造房子这个工作,是由两个特征鲜明的部分组成:构建各个成分和设计组装。在一个类中完成两项工作是不合适的,所以我们将把两个部分分开来做。
Builder 模式
首先我们来弄一个 Builder
类,用这个类做构建各个部分这件事情。
package builder;import house.House;public class Builder { House house = new House(); public void buildFloor(); public void buildWall(); public void buildWindows(); public void buildDoor(); public House getHouse();}
类里的 getHouse(): void
就是得到最终房子的方法。请注意,这个 Builer
只是“民工”,它不懂设计,只知道每一部分怎么弄。
“民工”需要一个设计师来指挥,设计师就是完成第二件事,设计组装的人。
package designer;import builder.Builder;/** * @author plus7wist * */public class Designer { public void concreteHouse(Builder builder) { builder.buildFloor(); builder.buildWall(); builder.buildDoor(); builder.buildWindows(); }}
代码里很明显可以看出,设计师其实什么都不干,它只是指挥 builder
进行工作,它的指挥体现出了设计的逻辑,而这一点 builder
又是不必操心的。
这种两者合作的结构就是典型的 Builder 模式。
扩展性
我们再看看这个设计进行扩展的时候会怎么样。无论风格怎么改变,Designer
的逻辑都不变。对于多样变化的 Builder
我们很容易想到一种解决办法:利用多态,将原来的 Builder
变成抽象的。
package builder;import house.House;public abstract class Builder { public abstract void buildFloor(); public abstract void buildWall(); public abstract void buildWindows(); public abstract void buildDoor(); public abstract House getHouse();}
为了表示方便我们简要的写一下 House
。用一个数组把成分的样子存起来。
package house;import java.util.ArrayList;public class House { private ArrayList<String> parts = new ArrayList<String>(); public void add(String part) { parts.add(part); } public void display() { for (int i = 0; i < parts.size(); ++i) System.out.print((i == 0 ? "" : ",") + parts.get(i)); System.out.println(); }}
然后如果建中国风格的房子的话,就建一个ChinaHouseBuilder
,继承自 Builder
。
package concrete.builder;import house.House;import builder.Builder;/** * @author plus7wist * */public class ChinaHouseBuilder extends Builder { House chinaHouse = new House(); @Override public void buildFloor() { chinaHouse.add("China Floor"); } @Override public void buildWall() { chinaHouse.add("China Wall"); } @Override public void buildWindows() { chinaHouse.add("China Windows"); } @Override public void buildDoor() { chinaHouse.add("China Door"); } @Override public House getHouse() { return chinaHouse; }}
如果建罗马风格的房子的话,就建一个RomeHouseBuilder
。
package concrete.builder;import house.House;import builder.Builder;/** * @author plus7wist * */public class RomeHouseBuilder extends Builder { House romeHouse = new House(); @Override public void buildFloor() { romeHouse.add("Rome Floor"); } @Override public void buildWall() { romeHouse.add("Rome Wall"); } @Override public void buildWindows() { romeHouse.add("Rome Windows"); } @Override public void buildDoor() { romeHouse.add("Rome Door"); } @Override public House getHouse() { return romeHouse; }}
如此一来,我们发现 Designer
的逻辑完全不用改——当真是个好的设计。
最后我们看一眼怎么使用这个东西。
package main;import builder.Builder;import house.House;import concrete.builder.*;import designer.Designer;/** * @author plus7wist * */public class Main { /** * @param args */ public static void main(String[] args) { Builder chinaHouseBuilder = new ChinaHouseBuilder(); Builder romeHouseBuilder = new RomeHouseBuilder(); Designer designer = new Designer(); designer.concreteHouse(chinaHouseBuilder); designer.concreteHouse(romeHouseBuilder); House chinaHouse = chinaHouseBuilder.getHouse(); House romeHouse = romeHouseBuilder.getHouse(); chinaHouse.display(); romeHouse.display(); }}
- builder 模式
- Builder模式
- Builder 模式
- Builder模式
- builder模式
- builder模式
- Builder模式
- builder模式
- Builder模式
- Builder 模式
- Builder 模式
- Builder模式
- Builder模式
- builder模式
- builder模式
- builder模式
- Builder模式
- Builder模式
- 使用mp4v2将H264+AAC合成mp4文件
- HOG特征(Histogram of Gradient)学习总结
- libevent杂谈
- Shell一键部署Auto.ps1
- VC++编译时错误 - 执行c windows system32 cmd.exe 时 出错
- Builder 模式
- [ECshop系统]ECShop验证码短信接口插件(2.7.3 UTF-8版)高级版V2
- OC篇学习-字符串
- Android之 如何在退出一个activity后,很好的取消AsyncTask继续运行
- 输出单层结点
- java NIO 和阻塞I/O的区别
- 南师oj1006
- 3-24博客
- setZOrder改名叫setlLocalZOrder