type
status
date
slug
summary
tags
category
icon
password

一、定义

notion image
建造者模式指的是一个复杂对象,它是由多个简单的对象组合,然后一步一步建构而成的

二、示例:

模拟场景: 很多装修公司都会给出⾃家的套餐服务,⼀般有;欧式豪华、轻奢⽥园、现代简约等等,⽽这些套餐的后⾯是不同的商品的组合。例如;⼀级&⼆级吊顶、多乐⼠涂料、圣象地板、⻢可波罗地砖等等,按照不同的套餐的价格选取不同的品牌组合,最终再按照装修⾯积给出⼀个整体的报价。
这⾥我们就模拟装修公司想推出⼀些套餐装修服务,按照不同的价格设定品牌选择组合,以达到使⽤建造者模式的过程。

传统硬编码方式(都在一个类里面实现,多重if else嵌套使用)

装修风格类:DecorationPackageController
package com.qf.design.create.builder.tradition; import com.qf.design.create.builder.entity.Matter; import com.qf.design.create.builder.entity.ceiling.LevelOneCeiling; import com.qf.design.create.builder.entity.ceiling.LevelTwoCeiling; import com.qf.design.create.builder.entity.coat.DuluxCoat; import com.qf.design.create.builder.entity.coat.LiBangCoat; import com.qf.design.create.builder.entity.floor.ShengXiangFloor; import com.qf.design.create.builder.entity.tile.DongPengTile; import com.qf.design.create.builder.entity.tile.MarcoPoloTile; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; 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("\r\n-------------------------------------------------------\r\n" +                "装修清单" + "\r\n" +                "套餐等级:" + level + "\r\n" +                "套餐价格:" + price.setScale(2, BigDecimal.ROUND_HALF_UP) + " 元\r\n" +                "房屋面积:" + area.doubleValue() + " 平米\r\n" +                "材料清单:\r\n");        for (Matter matter: list) {            detail.append(matter.scene()).append(":").append(matter.brand()).append("、").append(matter.model()).append("、平米价格:").append(matter.price()).append(" 元。\n");       }        return detail.toString();   } }
测试:ApiTest
package com.qf.design.create.builder.tradition; import java.math.BigDecimal; public class ApiTest {    public static void main(String[] args) {        DecorationPackageController controller=new DecorationPackageController();        String matterList = controller.getMatterList(new BigDecimal(125.6), 1);        System.out.println(matterList);   } }

建造者模式

任何的装修风格都是离不开基础的涂料、平层、瓷砖、吊顶。 抽象装修菜单接口:IMenu
package com.qf.design.create.builder.design; import com.qf.design.create.builder.entity.Matter; public interface IMenu {    /**     * 吊顶     */    IMenu appendCeiling(Matter matter);    /**     * 涂料     */    IMenu appendCoat(Matter matter);    /**     * 平层     */    IMenu appendFloor(Matter matter);    /**     * 瓷砖     */    IMenu appendTile(Matter matter);    /**     * 获取价格     */    String getPrice(); }
规则实现:DecoratePackageMenu
package com.qf.design.create.builder.design; import com.qf.design.create.builder.entity.Matter; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; public class DecoratePackageMenu implements IMenu {    private List<Matter> list = new ArrayList<Matter>();    private BigDecimal area;    private String grade;    private BigDecimal price=BigDecimal.ZERO;    public DecoratePackageMenu(Double area,String grade){        this.area=new BigDecimal(area);        this.grade=grade;   }    @Override    public IMenu appendCeiling(Matter matter) {        list.add(matter);        price=price.add(area.multiply(new BigDecimal("0.2")).multiply(matter.price()));        return this;   }    @Override    public IMenu appendCoat(Matter matter) {        list.add(matter);        price=price.add(area.multiply(new BigDecimal("1.4")).multiply(matter.price()));        return this;   }    @Override    public IMenu appendFloor(Matter matter) {        list.add(matter);        price=price.add(area.multiply(matter.price()));        return this;   }    @Override    public IMenu appendTile(Matter matter) {        list.add(matter);        price=price.add(area.multiply(matter.price()));        return this;   }    @Override    public String getPrice() {        StringBuilder detail = new StringBuilder("\r\n-------------------------------------------------------\r\n" +                "装修清单" + "\r\n" +                "套餐等级:" + grade + "\r\n" +                "套餐价格:" + price.setScale(2, BigDecimal.ROUND_HALF_UP) + " 元\r\n" +                "房屋面积:" + area.doubleValue() + " 平米\r\n" +                "材料清单:\r\n");        for (Matter matter: list) {            detail.append(matter.scene()).append(":").append(matter.brand()).append("、").append(matter.model()).append("、平米价格:").append(matter.price()).append(" 元。\n");       }        return detail.toString();   } }
每一种装修风格对应的是一种装修方法,加入新的风格,只需要扩展新的方法:Builder
package com.qf.design.create.builder.design; import com.qf.design.create.builder.entity.ceiling.LevelOneCeiling; import com.qf.design.create.builder.entity.ceiling.LevelTwoCeiling; import com.qf.design.create.builder.entity.coat.DuluxCoat; import com.qf.design.create.builder.entity.coat.LiBangCoat; import com.qf.design.create.builder.entity.floor.ShengXiangFloor; import com.qf.design.create.builder.entity.tile.DongPengTile; import com.qf.design.create.builder.entity.tile.MarcoPoloTile; public class Builder {    /**     * 一级品     * @param area     * @return     */    public IMenu levelOne(Double area){        return new DecoratePackageMenu(area,"豪华欧式")               .appendCeiling(new LevelTwoCeiling())               .appendCeiling(new DuluxCoat())               .appendCeiling(new ShengXiangFloor());   }    /**     * 三级品     * @param area     * @return     */    public IMenu levelTwo(Double area){        return new DecoratePackageMenu(area,"轻奢田园")               .appendCeiling(new LevelTwoCeiling())               .appendCeiling(new LiBangCoat())               .appendCeiling(new MarcoPoloTile());   }    /**     * 二级品     * @param area     * @return     */    public IMenu levelThree(Double area){        return new DecoratePackageMenu(area,"现代简约")               .appendCeiling(new LevelOneCeiling())               .appendCeiling(new LiBangCoat())               .appendCeiling(new DongPengTile());   } }
总结: 通过上⾯对建造者模式的使⽤,已经可以摸索出⼀点⼼得。那就是什么时候会选择这样的设计模 式,当: ⼀些基本物料不会变,⽽其组合经常变化的时候 ,就可以选择这样的设计模式来构建代码。
此设计模式满⾜了单⼀职责原则以及可复⽤的技术、建造者独⽴易扩展、便于控制细节⻛险。但 同时当出现特别多的物料以及很多的组合后,类的不断扩展也会造成难以维护的问题。但这种设计 结构模型可以把᯿复的内容抽象到数据库中,按照需要配置。这样就可以减少代码中⼤量的复。
 
JAVA【设计模式】工厂方法模式JAVA【设计模式】适配器模式