建造者模式 傳統方式實現 建造者模式

文章參考書籍:重學Java設計模式
作者:⼩傅哥

場景:
模擬裝修公司對於設計出⼀些套餐裝修服務的。
很多裝修公司都會給出⾃家的套餐服務,⼀般有;歐式豪華、輕奢⽥園、現代簡約等等,⽽這些套餐的後⾯是不同的商品的組合。例如;⼀級&⼆級吊頂、多樂⼠塗料、聖象地板、⻢可波羅地磚等等,按照不同的套餐的價格選取不同的品牌組合,最終再按照裝修⾯積給出⼀個整體的報價。這⾥我們就模擬裝修公司想推出⼀些套餐裝修服務,按照不同的價格設定品牌選擇組合

傳統方式實現

物料接口

import java.math.BigDecimal;

/**
 * 物料接口
 * 提供物料的基本信息
 */
public interface Matter {

    /**
     * 場景:地板、地磚、吊頂、塗料
     * @return
     */
    String scene();

    /**
     * 品牌
     * @return
     */
    String brand();

    /**
     * 型號
     * @return
     */
    String model();

    /**
     * 價格
     * @return
     */
    BigDecimal price();

    /**
     * 描述
     * @return
     */
    String desc();
}

一級吊頂

import com.ustcinfo.strategy.Matter;

import java.math.BigDecimal;

/**
 * 一級吊頂
 */
public class LevelOneCeiling implements Matter {
    @Override
    public String scene() {
        return "吊頂";
    }

    @Override
    public String brand() {
        return "裝修公司自帶";
    }

    @Override
    public String model() {
        return "一級頂";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(200);
    }

    @Override
    public String desc() {
        return "造型只做低一級,只有一個層次的吊頂,一般離頂120-150mm";
    }
}

二級吊頂

import com.ustcinfo.strategy.Matter;
import java.math.BigDecimal;

/**
 * 二級吊頂
 */
public class LevelTwoCeiling implements Matter {
    @Override
    public String scene() {
        return "吊頂";
    }

    @Override
    public String brand() {
        return "裝修公司自帶";
    }

    @Override
    public String model() {
        return "二級頂";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(800);
    }

    @Override
    public String desc() {
        return "兩個層次的吊頂,⼆級吊頂⾼度⼀般就往下吊20cm,要是層⾼很⾼,也可增加\n" +
                "每級的厚度";
    }
}

塗料-多樂士

import com.ustcinfo.strategy.Matter;
import java.math.BigDecimal;

/**
* 塗料 多樂士
*/
public class DuluxCoat implements Matter {
   @Override
   public String scene() {
       return "塗料";
   }

   @Override
   public String brand() {
       return "多樂士";
   }

   @Override
   public String model() {
       return "第二代";
   }

   @Override
   public BigDecimal price() {
       return new BigDecimal(700);
   }

   @Override
   public String desc() {
       return "多樂⼠是阿克蘇諾⻉爾旗下的著名建築裝飾油漆品牌,產品暢銷於全球100個國\n" +
               "家,每年全球有5000萬戶家庭使⽤多樂⼠油漆。";
   }
}

塗料-立邦

import com.ustcinfo.strategy.Matter;
import java.math.BigDecimal;

/**
 * 塗料 立邦
 */
public class LiBangCoat implements Matter {
    @Override
    public String scene() {
        return "塗料";
    }

    @Override
    public String brand() {
        return "立邦";
    }

    @Override
    public String model() {
        return "默認級別";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(600);
    }

    @Override
    public String desc() {
        return "⽴邦始終以開發綠⾊產品、注᯿⾼科技、⾼品質爲⽬標,以技術⼒量不斷推進科\n" +
                "研和開發,滿⾜消費者需求。";
    }
}

地板-德爾

import java.math.BigDecimal;
/**
 * 地板 德爾
 */
public class DerFloor implements Matter {
    @Override
    public String scene() {
        return "地板";
    }

    @Override
    public String brand() {
        return "德爾";
    }

    @Override
    public String model() {
        return "A+";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(120);
    }

    @Override
    public String desc() {
        return "DER德爾集團是全球領先的專業⽊地板製造商,北京2008年奧運會家裝和公裝\n" +
                "地板供應商";
    }
}

地板-聖象

import java.math.BigDecimal;

/**
 * 地板 聖象
 */
public class ShengXiangFloor implements Matter {
    @Override
    public String scene() {
        return "地板";
    }

    @Override
    public String brand() {
        return "聖象";
    }

    @Override
    public String model() {
        return "一級";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(310);
    }

    @Override
    public String desc() {
        return "聖象地板是中國地板⾏業著名品牌。聖象地板擁有中國馳名商標、中國名牌、國\n" +
                "家免檢、中國環境標誌認證等多項榮譽。";
    }
}

地磚-東鵬

import com.ustcinfo.strategy.Matter;
import java.math.BigDecimal;

/**
 * 地磚 東鵬
 */
public class DongPengTile implements Matter {
    @Override
    public String scene() {
        return "地磚";
    }

    @Override
    public String brand() {
        return "東鵬瓷磚";
    }

    @Override
    public String model() {
        return "10001";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(102);
    }

    @Override
    public String desc() {
        return "東鵬瓷磚以品質鑄就品牌,科技推動品牌,⼝碑傳播品牌爲宗旨,2014年品牌\n" +
                "價值132.35億元,位列建陶⾏業榜⾸。";
    }
}

地磚-馬可波羅

package com.ustcinfo.strategy.tile;
import com.ustcinfo.strategy.Matter;
import java.math.BigDecimal;

/**
 * 地磚 馬可波羅
 */
public class MarcoPoloTile implements Matter {
    @Override
    public String scene() {
        return "地磚";
    }

    @Override
    public String brand() {
        return "馬可波羅";
    }

    @Override
    public String model() {
        return "缺省";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(140);
    }

    @Override
    public String desc() {
        return "⻢可波羅品牌誕⽣於1996年,作爲國內最早品牌化的建陶品牌,以“⽂化陶\n" +
                "瓷”佔領市場,享有“仿古磚⾄尊”的美譽。";
    }
}

測試及運行結果

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class DecorationPackageController {

    public static String decoration(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();
    }

    public static void main(String[] args) {
        System.out.println(decoration(new BigDecimal(120.0), 1));
        System.out.println(decoration(new BigDecimal(97.0), 2));
        System.out.println(decoration(new BigDecimal(85.0), 3));

    }
}

-------------------------------------------------------
裝修清單
套餐等級:1
套餐價格:174000.00 元
房屋⾯積:120.0 平⽶
材料清單:
吊頂:裝修公司自帶、二級頂、平⽶價格:800 元。
塗料:多樂士、第二代、平⽶價格:700 元。
地板:聖象、一級、平⽶價格:310 元。


-------------------------------------------------------
裝修清單
套餐等級:2
套餐價格:110580.00 元
房屋⾯積:97.0 平⽶
材料清單:
吊頂:裝修公司自帶、二級頂、平⽶價格:800 元。
塗料:立邦、默認級別、平⽶價格:600 元。
地磚:馬可波羅、缺省、平⽶價格:140 元。


-------------------------------------------------------
裝修清單
套餐等級:3
套餐價格:83470.00 元
房屋⾯積:85.0 平⽶
材料清單:
吊頂:裝修公司自帶、一級頂、平⽶價格:200 元。
塗料:立邦、默認級別、平⽶價格:600 元。
地磚:東鵬瓷磚、10001、平⽶價格:102 元。

建造者模式

IMenu

public interface IMenu {
    /**
     * 吊頂
     * @param matter
     * @return
     */
    IMenu appendCeiling(Matter matter);

    /**
     * 塗料
     * @param matter
     * @return
     */
    IMenu appendCoat(Matter matter);

    /**
     * 地板
     * @param matter
     * @return
     */
    IMenu appendFloor(Matter matter);

    /**
     * 地磚
     * @param matter
     * @return
     */
    IMenu appendTile(Matter matter);

    /**
     * 明細
     * @return
     */
    String getDetail();
}

DecorationPackageMenu

是 IMenu 接⼝的實現類,主要是承載建造過程中的填充器。相當於
這是⼀套承載物料和創建者中間銜接的內容。

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;
    }

    /**
     * 明細
     * @return
     */
    public String getDetail() {
        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

建造者類具體的各種組裝由此類實現

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 Test_Builder {

    public static void main(String[] args) {
        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());
    }
}
測試結果:
-------------------- -----------------------------------
裝修清單
套餐等級:豪華歐式
套餐價格:192154.00 元
房屋⾯積:132.52 平⽶
材料清單:
吊頂:裝修公司自帶、二級頂、平⽶價格:800 元。
塗料:多樂士、第二代、平⽶價格:700 元。
地板:聖象、一級、平⽶價格:310 元。
-------------------- -----------------------------------
裝修清單
套餐等級:輕奢⽥園
套餐價格:112005.00 元
房屋⾯積:98.25 平⽶
材料清單:
吊頂:裝修公司自帶、二級頂、平⽶價格:800 元。
塗料:立邦、默認級別、平⽶價格:600 元。
地磚:馬可波羅、缺省、平⽶價格:140 元。


-------------------- -----------------------------------
裝修清單
套餐等級:現代簡約
套餐價格:83892.26 元
房屋⾯積:85.43 平⽶
材料清單:
吊頂:裝修公司自帶、一級頂、平⽶價格:200 元。
塗料:立邦、默認級別、平⽶價格:600 元。
地磚:東鵬瓷磚、10001、平⽶價格:102 元。

總結: 當⼀些基本物料不會變,⽽其組合經常變化的時候 ,就可以選擇這樣的設計模式來構建代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章