设计模式——建造者模式
介绍
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。一个Buider类会一步一步的构建最终的对象,该Builder类是独立于其他对象的。
何时使用
一些基本的部件不变,而其组合经常变化的时候
如何解决
将变与不变分离开
应用实例
麦当劳里的汉堡、可乐、薯条、炸鸡等是不变的,但其组合经常变动,生成所谓的“套餐”
注意
与工厂模式相比,更加关注与零件装配的顺序
案例
快餐店案例,其中一个典型的套餐可是一个汉堡(Burger)和一杯冷饮(Cold drink)。汉堡可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chiken Burer),他们装在纸盒里;冷饮可以是可口可乐(coke)或百事可乐(pepsi),他们装在瓶子里。
我们创建一个表示食物条目(比如汉堡和冷饮)的Item接口和实现Item接口的实体类,以及一个表示食物包装的Packing接口和实现Packing接口的实体类。汉堡包在纸盒里,可乐装在瓶子里。
然后我们创建一个Meal类,带有Item的ArrayList和一个通过Item来创建不同类型的Meal对象的MealBuilder。
步骤一
创建一个表示食物条目和食物包装的接口
Item.java
public interface Item { public String name(); public Packing packing(); public float price(); }
Packing.java
public interface Packing { public String pack(); }
步骤二
实现Packing接口的实体类
Wrapper.java
public class Wrapper implements Packing{ public String pack() { return "Wrapper"; } }
Bottle.java
public class Bottle implements Packing{ public String pack() { return "Bottle"; } }
步骤三
实现Item接口的抽象类,该类提供默认的功能
Burger.java
public abstract class Burger implements Item { public Packing packing(){ return new Wrapper(); } public abstract float price(); }
ColdDrink.java
public abstract class ColdDrink implements Item{ public Packing packing(){ return new Bottle(); } public abstract float price(); }
步骤四
创建扩展了Burger和ColdDrink的实体类
VegBurger.java
public class VegBurger extends Burger{ public float price(){ return 25.0f; } public String name(){ return "Veg Burger"; } }
ChickBurger.java
public class ChikenBurger extends Burger{ public float price(){ return 50.5f; } public String name(){ return "Chicken Burger"; } }
Cock.java
public class Coke extends ColdDrink{ public float price(){ return 30.0f; } public String name(){ return "Coke"; } }
Pepsi.java
public class Pepsi extends ColdDrink{ public float price(){ return 35.0f; } public String name(){ return "Pepsi"; } }
步骤五
创建一个Meal类,带有上面定义的Item对象
Meal.java
import java.util.List; import java.util.ArrayList; public class Meal { private List<Item> items = new ArrayList<Item>(); public void addItem(Item item){ items.add(item); } public float getCost(){ float cost = 0.0f; for (Item item: items){ cost += item.price(); } return cost; } public void showItems(){ for (Item item: items){ System.out.println("Item:" + item.name()); System.out.println(", Packing:" + item.packing().pack()); System.out.println(", Price:" + item.price()); } } }
步骤六
创建一个MealBuilder类,实际上builder类负责创建Meal对象,下面创建了2份套餐
MealBuilder.java
public class MealBuilder { public Meal prepareVegMeal(){ Meal meal = new Meal(); meal.addItem(new VegBurger()); meal.addItem(new Coke()); return meal; } public Meal prepareNonVegMeal(){ Meal meal = new Meal(); meal.addItem(new ChikenBurger()); meal.addItem(new Pepsi()); return meal; } }
步骤七
演示创建者模式
BuilderPatternDemo.java
public class BuilderPatternDeom { public static void main(String []args){ MealBuilder mealBuilder = new MealBuilder(); Meal vegMeal = mealBuilder.prepareVegMeal(); System.out.println("veg Meal"); vegMeal.showItems(); System.out.println("Total Cost:" + vegMeal.getCost()); Meal nonVegMeal = mealBuilder.prepareNonVegMeal(); System.out.println("mon veg Meal"); nonVegMeal.showItems(); System.out.println("Total Cost:" + nonVegMeal.getCost()); } }
步骤八
输出
veg Meal Item:Veg Burger , Packing:Wrapper , Price:25.0 Item:Coke , Packing:Bottle , Price:30.0 Total Cost:55.0 Disconnected from the target VM, address: '127.0.0.1:63309', transport: 'socket' mon veg Meal Item:Chicken Burger , Packing:Wrapper , Price:50.5 Item:Pepsi , Packing:Bottle , Price:35.0 Total Cost:85.5