设计模式之禅6
来源:互联网 发布:无线点菜机软件 编辑:程序博客网 时间:2024/06/05 02:53
设计模式之禅6
真刀实枪之建造者模式
变化是永恒的--悍马车的私人订制
- 汽车的启动,停止,喇叭声音,引擎声音都有客户控制
- 先看类图吧,简单设计下:顺序如何由sequence来决定
代码
CarModel抽象类
package com.peng.builder;import java.util.ArrayList;/** * @author kungfu~peng * @data 2017年11月16日 * @description */public abstract class CarModel { private ArrayList<String> sequence=new ArrayList<String>();F // 发动车 public abstract void start(); // 停车 public abstract void stop(); // 响喇叭 public abstract void alarm(); // 引擎 public abstract void engineBoom(); // // 运行 final public void run() { for(String s:sequence){ if("start".equals(s)){ this.start(); }else if("stop".equals(s)){ this.stop(); }else if("alarm".equals(s)){ this.alarm(); }else if("engineBoom".equals(s)){ this.engineBoom(); } } } //把传递过来的值传递到类中 final public void setSequence(ArrayList<String> sequence){ this.sequence=sequence; }}
悍马类
package com.peng.builder;/** * @author kungfu~peng * @data 2017年11月16日 * @description */public class HummerCarModel extends CarModel { @Override public void start() { System.out.println("悍马跑起来!"); } @Override public void stop() { System.out.println("悍马停车!"); } @Override public void alarm() { System.out.println("悍马的喇叭声!"); } @Override public void engineBoom() { System.out.println("悍马的引擎发动!"); }}
测试类
package com.peng.builder;import java.util.ArrayList;/** * @author kungfu~peng * @data 2017年11月16日 * @description */public class Test { public static void main(String[] args) { // 创建悍马车模型 HummerCarModel hummer = new HummerCarModel(); // 创建执行顺序 ArrayList<String> list = new ArrayList<String>(); list.add("start"); list.add("alarm"); list.add("engineBoom"); list.add("stop"); // 按客户的顺序执行 hummer.setSequence(list); hummer.run(); }}
- 上述代码中,汽车的动作的执行顺序是可以随意指定的,我们也只满足了这一个条件而已,还有下一个下下一个需求...直到把你逼疯为之。那怎么办,我们写场景类来一个个的控制吗,显然是不合理的。有了,我们为模型产品模型定义一个建造者,你要啥顺序直接告诉建造者,由建造者来建造。
- 改造的类图
如类图,增加了一个CarBuilder抽象类,由他来组装各个车模
CarBuilder
package com.peng.builder;import java.util.ArrayList;/** * @author kungfu~peng * @data 2017年11月16日 * @description */public abstract class CarBuilder { // 建造一个模型,提供一个组装顺序 public abstract void setSequence(ArrayList<String> sequence); // 获得车辆模型 public abstract CarModel getCarModel();}
HummerBuilder
package com.peng.builder;import java.util.ArrayList;/** * @author kungfu~peng * @data 2017年11月16日 * @description */public class HummerBuilder extends CarBuilder { private HummerCarModel hummer = new HummerCarModel(); @Override public void setSequence(ArrayList<String> sequence) { this.hummer.setSequence(sequence); } @Override public CarModel getCarModel() { return hummer; }}
CarModel
package com.peng.builder;import java.util.ArrayList;/** * @author kungfu~peng * @data 2017年11月16日 * @description */public abstract class CarModel { private ArrayList<String> sequence = new ArrayList<String>(); // 发动车 public abstract void start(); // 停车 public abstract void stop(); // 响喇叭 public abstract void alarm(); // 引擎 public abstract void engineBoom(); // // 运行 final public void run() { for (String s : sequence) { if ("start".equals(s)) { this.start(); } else if ("stop".equals(s)) { this.stop(); } else if ("alarm".equals(s)) { this.alarm(); } else if ("engineBoom".equals(s)) { this.engineBoom(); } } } // 把传递过来的值传递到类中 final public void setSequence(ArrayList<String> sequence) { this.sequence = sequence; }}
HummerCarModel
package com.peng.builder;/** * @author kungfu~peng * @data 2017年11月16日 * @description */public class HummerCarModel extends CarModel { @Override public void start() { System.out.println("悍马跑起来!"); } @Override public void stop() { System.out.println("悍马停车!"); } @Override public void alarm() { System.out.println("悍马的喇叭声!"); } @Override public void engineBoom() { System.out.println("悍马的引擎发动!"); }}
测试类
package com.peng.builder;import java.util.ArrayList;/** * @author kungfu~peng * @data 2017年11月16日 * @description */public class Test { public static void main(String[] args) { // 创建执行顺序 ArrayList<String> list = new ArrayList<String>(); list.add("start"); list.add("alarm"); list.add("engineBoom"); list.add("stop"); HummerBuilder hb = new HummerBuilder(); hb.setSequence(list); // 获得悍马车 HummerCarModel hummer = (HummerCarModel) hb.getCarModel(); // 执行hummer的run方法 hummer.run(); }}
同样的顺序的悍马车也制造出来了,而且代码也比之间访问简单了许多,在做项目的过程中,需求是个无底洞。客户是上帝,我们不能预知他们的顺序, 那该怎么办?封装一下,找一个导演,指挥各个事件的先后顺序,然后为每种顺序指定一个代码,然后你说一种我们立刻生产处理。
- 类图如下
代码
Direct类
package com.peng.builder;import java.util.ArrayList;/** * @author kungfu~peng * @data 2017年11月16日 * @description */public class Director { private ArrayList<String> sequence = new ArrayList<String>(); private HummerBuilder hb = new HummerBuilder(); // 获得悍马1 public CarModel getHummerCarModel1() { // 清空列表 sequence.clear(); sequence.add("start"); sequence.add("alarm"); sequence.add("engineBoom"); sequence.add("stop"); hb.setSequence(sequence); return hb.getCarModel(); } // 获得悍马2 public CarModel getHummerCarModel2() { // 清空列表 sequence.clear(); sequence.add("alarm"); sequence.add("engineBoom"); sequence.add("start"); sequence.add("stop"); hb.setSequence(sequence); return hb.getCarModel(); } // 获得悍马3 public CarModel getHummerCarModel3() { // 清空列表 sequence.clear(); sequence.add("stop"); sequence.add("start"); sequence.add("alarm"); sequence.add("engineBoom"); hb.setSequence(sequence); return hb.getCarModel(); }}
测试类(Client用test来写~~)
package com.peng.builder;import java.util.ArrayList;/** * @author kungfu~peng * @data 2017年11月16日 * @description */public class Test { public static void main(String[] args) { // 创建导演 Director director = new Director(); // 获得悍马车1 HummerCarModel hummer1 = (HummerCarModel) director.getHummerCarModel1(); // 执行hummer的run方法 System.out.println("悍马车1~~~~~"); hummer1.run(); // 获得悍马车2 HummerCarModel hummer2 = (HummerCarModel) director.getHummerCarModel2(); // 执行hummer的run方法 System.out.println("悍马车2~~~~~"); hummer2.run(); // 获得悍马车3 HummerCarModel hummer3 = (HummerCarModel) director.getHummerCarModel3(); // 执行hummer的run方法 System.out.println("悍马车3~~~~~"); hummer3.run(); }}
- 清晰吧,简单吧,我们写程序的最终目的是:简单清晰。代码是让人看的,不是写完就完了。
建造者模式的定义
- Builder Pattern
- 也叫做生成器模式
- Separate the construction of a complex object from its representation so that same construction process can create different representations(将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示)
- 通用类图
- 建造者中有四个角色
1. Product产品类2. Builder抽象建造者类3. ConcreteBuilder具体建造者类4. Director导演类
- 建造者中有四个角色
- 通用代码
- 产品类
public class Product{ public void doSomething(){ //独立业务处理 }}
- 抽象建造者类
public abstract class Builder{ //设置产品的不同部分,以获得不同的产品 public abstract void setPart(); //建造产品 public abstract Product buildProduct();}
- 具体建造者类
public class ConcreteProduct extends Builder{ private Product product=new Product(); //设置产品零件 public void setPart(){ //产品类的逻辑处理 } //组建一个产品 public Product buildProduct(){ return product; }}
- 导演类
public class Direct{ private Builder builder=new ConcreteBuilder(); //构建不同的产品 public Product getAProduct(){ builder.setPart(); return builder.buildProduct(); }}
- 产品类
建造者模式的应用
- 建造者模式的优点
1. 封装性2. 建造者独立,容易扩展3. 便于控制细节风险
- 建造者模式的使用场景
1. 相同的方法,不同的执行顺序,产生不同的执行结果2. 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同3. 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能4. 在创建对象的过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中,不易得到时--这种方法只是一个补偿方法,因为一个对象不容易获得,而在设计阶段竟然没有发觉,而要通过创建者模式柔化创建过程,本身已经违反了设计的最初目标
建造者的注意事项
- 关注零件类型和装配的工艺(顺序),这是它与工厂方法的最大的不同地方
扩展
- 建造者模式+模板模式(比如加入导演类的悍马的生产过程中)
- 建造者的核心思想:零件的组装,组装的顺序不同,效能也不同
- 与工厂模式的对比
- 工厂模式的任务是对对象的创建感兴趣,如何创建的细节并不关心
- 建造者模式的最主要的功能是基本方法的调用顺序安排,也就是这些基本的方法已经实现了,通俗的讲也就是零件的装配,顺序的不同产生的对象也不同。
- 工厂模式的重点是创建,,创建零件是它关心的,组装是它所不关心的
最佳实践
- 【建造者模式+模板模式】记得用哦!
- 别孤立的使用一个模式,僵化的使用一个模式会让你受害无穷
声明
- 摘自秦小波《设计模式之禅》第2版;
- 仅供学习,严禁商业用途;
- 代码手写,没有经编译器编译,有个别错误,自行根据上下文改正。
阅读全文
0 0
- 设计模式之禅6
- 设计模式之禅
- 设计模式之禅
- 设计模式之禅
- 设计模式之禅
- 设计模式之禅
- 设计模式之禅
- 设计模式之禅
- 设计模式之禅笔记6
- 《设计模式之禅》——6大设计原则
- 设计模式之禅笔记-6大设计原则(上)
- 设计模式之禅笔记-6大设计原则(下)
- [设计模式]<<设计模式之禅>>模板方法模式
- 《设计模式之禅》目录
- 《设计模式之禅》前言
- 《设计模式之禅》书评
- 《设计模式之禅》书评
- 初读《设计模式之禅》
- 矩阵基本运算
- 项目中遇到的坑以及解决办法(导师辅助工作)
- /bin/sh: /tmp/IP172.sh: 权限不够
- 面向对象程序设计上机练习六(类和对象)
- Java虚拟机类加载机制
- 设计模式之禅6
- Android自定义控件之基本原理 转载自(总李写代码)
- 机器学习课后作业笔记(一)
- Redis 学习笔记(七)之 有序集合
- URL中“#” “?” &“”号的作用
- 嵌入式10月就业榜万众一“薪” 全国平均薪资9645.5元
- 关于程序员之间丧心病狂的鄙视链——编程语言篇
- 自定义View,转载大神的页面
- 常用的正则表达式