Design Pattern

Chapter 4 建造者模式(Builder Pattern)

定義

將一個複雜對象的構建與他的表示分離,使得同樣的構建過程可以創建不同的表示。 一步一步創建一個複雜的對象,它允許用戶只通過指定複雜對象的類型和內容就可以建構它們,用戶不需要知道內部的具體建構細節。

建造者模式客戶端返回的不是一個簡單的產品,而是一個由多個部件組成的複雜產品。

差異

工廠類模式:創建單個類的模式(關注單個產品)
建造者模式:將各種產品集中起來進行管理(關注複合對象)

組成

  1. 抽象建造者(Builder):為創建具體產品的具體建造者提供接口
  2. 具體建造者(ConcreteBuilder):建造具體產品
  3. 指揮者(Director):調用Builder接口來創建產品對象
  4. 產品角色(Product):具體產品

程式碼

Step1

public interface Packing {
    public String pack();
}


public interface Item {
    public String name();
    public Packing packing();
    public float price();
}

Step2

public class Wrapper implements Packing{
    @Override
    public String pack() {
        return "紙盒";
    }
}


public class Bottle implements Packing{
    @Override
    public String pack() {
        return "紙杯";
    }
}

Step3

public abstract class Burger implements Item{
    @Override
    public Packing packing() {
        return new Wrapper();
    }

    @Override
    public abstract float price();
}


public abstract class ColdDrink implements Item{
    @Override
    public Packing packing() {
        return new Bottle();
    }

    @Override
    public abstract float price();
}

Step4

public class VegBurger extends Burger{
    @Override
    public String name() {
        return "蔬菜漢堡";
    }

    @Override
    public float price() {
        return 30;
    }
}

public class ChickenBurger extends Burger{
    @Override
    public String name() {
        return "雞肉漢堡";
    }

    @Override
    public float price() {
        return 35;
    }
}

public class Coke extends ColdDrink{
    @Override
    public String name() {
        return "可樂";
    }

    @Override
    public float price() {
        return 30;
    }
}

public class BlackTea extends ColdDrink{
    @Override
    public String name() {
        return "紅茶";
    }

    @Override
    public float price() {
        return 25;
    }
}

Step5

public class Meal {
    private List<Item> items = new ArrayList<Item>();

    public void addItem(Item item){
        items.add(item);
    }
    public float getCost(){
        float cost = 0;
        for(Item item: items){
            cost += item.price();
        }
        return cost;
    }

    public void showItem(){
        for(Item item : items){
            System.out.print("Item : " + item.name());
            System.out.print(", Packing : " + item.packing().pack());
            System.out.println(", Price : " + item.price());
        }
    }
}

Step6

public class MealBuilder {
    public Meal prepareVegMeal (){
        Meal meal = new Meal();
        meal.addItem(new VegBurger());
        meal.addItem(new Coke());
        return meal;
    }   

    public Meal prepareChickenMeal (){
        Meal meal = new Meal();
        meal.addItem(new ChickenBurger());
        meal.addItem(new BlackTea());
        return meal;
    }
}

Step7

public static void main(String[] args) {

          MealBuilder mealBuilder = new MealBuilder();

          Meal vegMeal = mealBuilder.prepareVegMeal();
          System.out.println("蔬菜套餐");
          vegMeal.showItem();
          System.out.println("價格: " + vegMeal.getCost());

          Meal nonVegMeal = mealBuilder.prepareChickenMeal();
          System.out.println("\n\n雞肉套餐");
          nonVegMeal.showItem();
          System.out.println("價格: " + nonVegMeal.getCost());
}

Step8(Output)

蔬菜套餐
Item : 蔬菜漢堡, Packing : 紙盒, Price : 30.0
Item : 可樂, Packing : 紙杯, Price : 30.0
價格: 60.0

雞肉套餐
Item : 雞肉漢堡, Packing : 紙盒, Price : 35.0
Item : 紅茶, Packing : 紙杯, Price : 25.0
價格: 60.0

優點

  1. 在建造者模式中,客戶端不必知道產品內部組成細節。
  2. 每一個具體建造者都相對獨立,與其他具體建造者無關,因此可以方便的替換具體建造者或增加新的具體建造者。
  3. 可以更加精細地控制產品創建的過程。

缺點

  1. 建造者模式所創建的產品一般具有較多的共同點,其組成部分相似,如果產品之間的差異性很大,則不適用建造者模式,因此使用範圍受到限制。
  2. 如果產品的內部變化複雜,可能會導致需要定義很多具體建造者來實現這種變化,導致系統變龐大。