JAVA【设计模式】建造者模式

一、定义

在这里插入图片描述

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

二、示例:

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

这⾥我们就模拟装修公司想推出⼀些套餐装修服务,按照不同的价格设定品牌选择组合,以达到使⽤建造者模式的过程。

传统硬编码方式(都在一个类里面实现,多重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());
    }

}

总结:
通过上⾯对建造者模式的使⽤,已经可以摸索出⼀点⼼得。那就是什么时候会选择这样的设计模
式,当: ⼀些基本物料不会变,⽽其组合经常变化的时候 ,就可以选择这样的设计模式来构建代码。

此设计模式满⾜了单⼀职责原则以及可复⽤的技术、建造者独⽴易扩展、便于控制细节⻛险。但
同时当出现特别多的物料以及很多的组合后,类的不断扩展也会造成难以维护的问题。但这种设计
结构模型可以把᯿复的内容抽象到数据库中,按照需要配置。这样就可以减少代码中⼤量的᯿复。

posted @ 2022-08-30 22:40  雾托邦  阅读(46)  评论(0编辑  收藏  举报