1. 建造者模式概述

使用多个简单对象来构造一个复杂的对象。

(1) 适用情况

构造一个复杂对象的内部组件不变,但是这些内部组建的组合方式经常变化的时候,可以考虑使用建造者模式。

(2) 优点

建造者独立,易扩展

(3) 缺点

  1. 产品必须有共同点,范围有限制
  2. 不适用于内部组件经常发生变动的情况

2. 建造者模式实例

我们现在要设计一个简单的外卖系统,系统中提供各种套餐,套餐中可以包含食物和饮料。
(1) 先实现一个Item类,表示所有的食物和饮料的基类,它还实现了Packing接口,这样每个Item就可以进行打包了

public abstract class Item implements Packing {
    // 物品名称
    private String name;

    // 物品价格
    private int price;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }
}
public interface Packing {
    // 打包
    String packing();
}

(2) 外卖中可以包括食物Food和饮料Drink,它们都继承于Item类,且实现不同的打包方式

public abstract class Food extends Item implements Box {
    // 食物是用盒子打包
}

public abstract class Drink extends Item implements Bottle {
    // 饮料是用瓶子打包
}

(3) 打包方式可以分为盒装和瓶装

public interface Box extends Packing {
    @Override
    default String packing() {
        // 盒装
        return "Box";
    }
}

public interface Bottle extends Packing {
    @Override
    default String packing() {
        // 瓶装
        return "Bottle";
    }
}

(4) 实现具体的食物和饮料

public class Rice extends Food {
    public Rice() {
        // 米饭价格15元
        this.setName("Rice");
        this.setPrice(15);
    }
}

public class Noodles extends Food{
    public Noodles() {
        // 面条价格12元
        this.setName("Noodles");
        this.setPrice(12);
    }
}

public class Coke extends Drink {
    public Coke() {
        // 可乐价格4元
        this.setName("Coke");
        this.setPrice(4);
    }
}

public class Spirit extends Drink {
    public Spirit() {
        // 雪碧价格3元
        this.setName("Spirit");
        this.setPrice(3);
    }
}

(5) 实现套餐类

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

    // 打印套餐总价
    public void printCost() {
        int cost = 0;
        for (Item item : items) {
            cost += item.getPrice();
        }
        System.out.println("Cost: " + cost);
    }

    // 打印套餐内容
    public void printItems() {
        for (Item item : items) {
            System.out.print("Item: " + item.getName());
            System.out.print(", Packing: " + item.packing());
            System.out.println(", Price : " + item.getPrice());
        }
    }

    // 套餐增加内容
    public void addItem(Item item) {
        this.items.add(item);
    }
}

(6) 实现套餐的建造者类

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

    public Meal buyMeal2() {
        Meal meal = new Meal();
        meal.addItem(new Noodles());
        meal.addItem(new Spirit());
        return meal;
    }
}

(7) 点外卖

public class BuilderPatternDemo {
    public static void main(String[] args) {
        MealBuilder builder = new MealBuilder();

        Meal meal1 = builder.buyMeal1();
        meal1.printItems();
        meal1.printCost();

        Meal meal2 = builder.buyMeal2();
        meal2.printItems();
        meal2.printCost();
    }
}

3. 一些思考

这个例子中的复杂对象就是套餐,而简单对象就是各种食物和饮料。

它们都是派生自Item类,即都有共同点。

食物和饮料不会经常变化,而套餐却经常会变。
如果需要增加新的套餐,只需要在MealBuilder类中增加套餐即可。

参考引用

建造者模式:http://it028.com/builder-patt...


Zealf
13 声望1 粉丝