设计模式之禅【建造者模式】

真刀实枪之建造者模式

  • 变化是永恒的--悍马车的私人订制

    • 汽车的启动,停止,喇叭声音,引擎声音都有客户控制
    • 先看类图吧,简单设计下:顺序如何由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
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

乘风御浪云帆之上

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

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

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

打赏作者

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

抵扣说明:

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

余额充值