zoukankan      html  css  js  c++  java
  • 设计模式-建造者模式

    建造者模式

    适用场景:

    一些基本物料不会变,而其组合经常变化的时候,可以选择建造者模式来改造代码

    案例:模拟装修公司对于设计出一些套餐装修服务的场景

    装修物料接口:Matter

    /**
     * 装修物料
     */
    public interface Matter {
    
        /**
         * 场景;地板、地砖、涂料、吊顶
         */
        String scene();
    
        /**
         * 品牌
         */
        String brand();
    
        /**
         * 型号
         */
        String model();
    
        /**
         * 平米报价
         */
        BigDecimal price();
    
        /**
         * 描述
         */
        String desc();
    
    }
    

    吊顶(ceiling)

    • 一级顶

      /**
       * 吊顶
       * 品牌;装修公司自带
       * 型号:一级顶
       */
      public class LevelOneCeiling implements Matter {
      
          public String scene() {
              return "吊顶";
          }
      
          public String brand() {
              return "装修公司自带";
          }
      
          public String model() {
              return "一级顶";
          }
      
          public BigDecimal price() {
              return new BigDecimal(260);
          }
      
          public String desc() {
              return "造型只做低一级,只有一个层次的吊顶,一般离顶120-150mm";
          }
      
      }
      
    • 二级顶

      public class LevelTwoCeiling  implements Matter {
      
          public String scene() {
              return "吊顶";
          }
      
          public String brand() {
              return "装修公司自带";
          }
      
          public String model() {
              return "二级顶";
          }
      
          public BigDecimal price() {
              return new BigDecimal(850);
          }
      
          public String desc() {
              return "两个层次的吊顶,二级吊顶高度一般就往下吊20cm,要是层高很高,也可增加每级的厚度";
          }
          
      }
      

    涂料

    • 多乐土

      /**
       * 涂料
       * 品牌;多乐士(Dulux)
       */
      public class DuluxCoat  implements Matter {
      
          public String scene() {
              return "涂料";
          }
      
          public String brand() {
              return "多乐士(Dulux)";
          }
      
          public String model() {
              return "第二代";
          }
      
          public BigDecimal price() {
              return new BigDecimal(719);
          }
      
          public String desc() {
              return "多乐士是阿克苏诺贝尔旗下的著名建筑装饰油漆品牌,产品畅销于全球100个国家,每年全球有5000万户家庭使用多乐士油漆。";
          }
          
      }
      
    • 立邦

      public class LiBangCoat implements Matter {
      
          public String scene() {
              return "涂料";
          }
      
          public String brand() {
              return "立邦";
          }
      
          public String model() {
              return "默认级别";
          }
      
          public BigDecimal price() {
              return new BigDecimal(650);
          }
      
          public String desc() {
              return "立邦始终以开发绿色产品、注重高科技、高品质为目标,以技术力量不断推进科研和开发,满足消费者需求。";
          }
      
      }
      

    然后是地板的几个品牌,地砖的几个品牌,和上边一样,实现matter接口

    ifelse实现

    public class DecorationPackageController {
    
        public String getMatterList(BigDecimal area, Integer level) {
    
            List<Matter> list = new ArrayList<Matter>(); // 装修清单
            BigDecimal price = BigDecimal.ZERO;          // 装修价格
    
            // 豪华欧式
            if (1 == level) {
    
                LevelTwoCeiling levelTwoCeiling = new LevelTwoCeiling(); // 吊顶,二级顶
                DuluxCoat duluxCoat = new DuluxCoat();                   // 涂料,多乐士
                ShengXiangFloor shengXiangFloor = new ShengXiangFloor(); // 地板,圣象
    
                list.add(levelTwoCeiling);
                list.add(duluxCoat);
                list.add(shengXiangFloor);
    
                price = price.add(area.multiply(new BigDecimal("0.2")).multiply(levelTwoCeiling.price()));
                price = price.add(area.multiply(new BigDecimal("1.4")).multiply(duluxCoat.price()));
                price = price.add(area.multiply(shengXiangFloor.price()));
    
            }
    
            // 轻奢田园
            if (2 == level) {
    
                LevelTwoCeiling levelTwoCeiling = new LevelTwoCeiling(); // 吊顶,二级顶
                LiBangCoat liBangCoat = new LiBangCoat();                // 涂料,立邦
                MarcoPoloTile marcoPoloTile = new MarcoPoloTile();       // 地砖,马可波罗
    
                list.add(levelTwoCeiling);
                list.add(liBangCoat);
                list.add(marcoPoloTile);
    
                price = price.add(area.multiply(new BigDecimal("0.2")).multiply(levelTwoCeiling.price()));
                price = price.add(area.multiply(new BigDecimal("1.4")).multiply(liBangCoat.price()));
                price = price.add(area.multiply(marcoPoloTile.price()));
    
            }
    
            // 现代简约
            if (3 == level) {
    
                LevelOneCeiling levelOneCeiling = new LevelOneCeiling();  // 吊顶,二级顶
                LiBangCoat liBangCoat = new LiBangCoat();                 // 涂料,立邦
                DongPengTile dongPengTile = new DongPengTile();           // 地砖,东鹏
    
                list.add(levelOneCeiling);
                list.add(liBangCoat);
                list.add(dongPengTile);
    
                price = price.add(area.multiply(new BigDecimal("0.2")).multiply(levelOneCeiling.price()));
                price = price.add(area.multiply(new BigDecimal("1.4")).multiply(liBangCoat.price()));
                price = price.add(area.multiply(dongPengTile.price()));
            }
    
            StringBuilder detail = new StringBuilder("
    -------------------------------------------------------
    " +
                    "装修清单" + "
    " +
                    "套餐等级:" + level + "
    " +
                    "套餐价格:" + price.setScale(2, BigDecimal.ROUND_HALF_UP) + " 元
    " +
                    "房屋面积:" + area.doubleValue() + " 平米
    " +
                    "材料清单:
    ");
    
            for (Matter matter: list) {
                detail.append(matter.scene()).append(":").append(matter.brand()).append("、").append(matter.model()).append("、平米价格:").append(matter.price()).append(" 元。
    ");
            }
    
            return detail.toString();
    
        }
    
    }
    

    通过传递的参数来判断是做什么风格的装修,然后分别单独构建装修材料,然后组合起来,计算价格

    建造者模式重构代码

    工程结构如图:

    image

    建造者模型结构:

    image

    • Builder类,建造者类具体的各类组装由此类实现。
    • DecorationPackageMenu类,实现Imenu接口,通过list放置要装修的材料,保存价格的变量,装修风格的变量和面积的变量都是通过构造函数的参数传递进来

    代码实现:

    • Imenu接口:

      public interface IMenu {
      
          /**
           * 吊顶
           */
          IMenu appendCeiling(Matter matter);
      
          /**
           * 涂料
           */
          IMenu appendCoat(Matter matter);
      
          /**
           * 地板
           */
          IMenu appendFloor(Matter matter);
      
          /**
           * 地砖
           */
          IMenu appendTile(Matter matter);
      
          /**
           * 明细
           */
          String getDetail();
      
      }
      

      接口类中定义了填充各项物料的方法; 吊顶 、 涂料 、 地板 、 地砖 ,以及最终提供获取全部明细的方法。

    • 装修包的实现

      public class DecorationPackageMenu implements IMenu {
      
          private List<Matter> list = new ArrayList<Matter>();  // 装修清单
          private BigDecimal price = BigDecimal.ZERO;      // 装修价格
      
          private BigDecimal area;  // 面积
          private String grade;     // 装修等级;豪华欧式、轻奢田园、现代简约
      
          private DecorationPackageMenu() {
          }
      
          public DecorationPackageMenu(Double area, String grade) {
              this.area = new BigDecimal(area);
              this.grade = grade;
          }
      
          public IMenu appendCeiling(Matter matter) {
              list.add(matter);
              price = price.add(area.multiply(new BigDecimal("0.2")).multiply(matter.price()));
              return this;
          }
      
          public IMenu appendCoat(Matter matter) {
              list.add(matter);
              price = price.add(area.multiply(new BigDecimal("1.4")).multiply(matter.price()));
              return this;
          }
      
          public IMenu appendFloor(Matter matter) {
              list.add(matter);
              price = price.add(area.multiply(matter.price()));
              return this;
          }
      
          public IMenu appendTile(Matter matter) {
              list.add(matter);
              price = price.add(area.multiply(matter.price()));
              return this;
          }
      
          public String getDetail() {
      
              StringBuilder detail = new StringBuilder("
      -------------------------------------------------------
      " +
                      "装修清单" + "
      " +
                      "套餐等级:" + grade + "
      " +
                      "套餐价格:" + price.setScale(2, BigDecimal.ROUND_HALF_UP) + " 元
      " +
                      "房屋面积:" + area.doubleValue() + " 平米
      " +
                      "材料清单:
      ");
      
              for (Matter matter: list) {
                  detail.append(matter.scene()).append(":").append(matter.brand()).append("、").append(matter.model()).append("、平米价格:").append(matter.price()).append(" 元。
      ");
              }
      
              return detail.toString();
          }
      
      }
      
      • 装修包的实现中每一个方法都返回了 this ,也就可以非常方便的用于连续填充各项物料
      • 同时在填充时也会根据物料计算平米数下的报价,吊顶和涂料按照平米数乘以该类定义的price计算
      • 最后同样提供了统一的获取装修清单的明细方法。
    • 建造者方法

      public class Builder {
      
          public IMenu levelOne(Double area) {
              return new DecorationPackageMenu(area, "豪华欧式")
                      .appendCeiling(new LevelTwoCeiling())    // 吊顶,二级顶
                      .appendCoat(new DuluxCoat())             // 涂料,多乐士
                      .appendFloor(new ShengXiangFloor());     // 地板,圣象
          }
      
          public IMenu levelTwo(Double area){
              return new DecorationPackageMenu(area, "轻奢田园")
                      .appendCeiling(new LevelTwoCeiling())   // 吊顶,二级顶
                      .appendCoat(new LiBangCoat())           // 涂料,立邦
                      .appendTile(new MarcoPoloTile());       // 地砖,马可波罗
          }
      
          public IMenu levelThree(Double area){
              return new DecorationPackageMenu(area, "现代简约")
                      .appendCeiling(new LevelOneCeiling())   // 吊顶,二级顶
                      .appendCoat(new LiBangCoat())           // 涂料,立邦
                      .appendTile(new DongPengTile());        // 地砖,东鹏
          }
      
      }
      

      统一的建造⽅方式,通过不同物料填充出不同的装修风格; 豪华欧式 、 轻奢⽥田园 、 现代简约等

    编写测试类

    public class ApiTest {
    
        @Test
        public void test_Builder(){
            Builder builder = new Builder();
    
            // 豪华欧式
            System.out.println(builder.levelOne(132.52D).getDetail());
    
            // 轻奢田园
            System.out.println(builder.levelTwo(98.25D).getDetail());
    
            // 现代简约
            System.out.println(builder.levelThree(85.43D).getDetail());
        }
    
    }
    
  • 相关阅读:
    现在的企业用到的Java开发主流框架有哪些
    StringBuffer清空
    java代码优化写法1(转摘)
    java代码优化写法(转摘)
    mysql常用
    java软引用、弱引用(转摘)
    mybtais分批insert
    大魔王降临cnblogs了~~
    tomcat去除项目名部署
    静态代码块、非静态代码块、构造函数的输出顺序
  • 原文地址:https://www.cnblogs.com/RealGang/p/14709659.html
Copyright © 2011-2022 走看看