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());
        }
    
    }
    
  • 相关阅读:
    陶瓷电容的结构、工艺、失效模式
    Vue.js最佳实践
    Vue 超快速学习
    CSS 小技巧
    HTML5 Canvas
    webkit下面的CSS设置滚动条
    Some untracked working tree files would be overwritten by checkout. Please move or remove them before you can checkout. View them
    JSCS: Please specify path to 'JSCS' package
    React中ref的使用方法
    React 60S倒计时
  • 原文地址:https://www.cnblogs.com/RealGang/p/14709659.html
Copyright © 2011-2022 走看看