建造者模式
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
实现
我们假设一个快餐店的商业案例,其中,一个典型的套餐可以是一个汉堡(Burger)和一杯冷饮(Cold drink)。汉堡(Burger)可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chicken Burger),它们是包在纸盒中。冷饮(Cold drink)可以是可口可乐(coke)或百事可乐(pepsi),它们是装在瓶子中。下面将用代码来实现这一过程,话不多说,直接上代码:
首先,我们创建一个Item的接口,里面有我们需要的方法:
/**
* 表示食物条目和食物包装
* @author ZSH
*
*/
public interface Item {
public String name();
public Packing packing();
public float price();
}
由于我们没有Packing类型的返回,所以我们要自己定义包装的类型,创建一个Packing接口:
/**
* 食物的包装类型:纸和瓶
* @author ZSH
*
*/
public interface Packing {
public String pack();
}
然后将我们想要的包装类型来分别实现Packing:
/**
* 包装类型纸封
* @author ZSH
*
*/
public class Wrapper implements Packing {
@Override
public String pack() {
// TODO Auto-generated method stub
return "Wrapper";
}
}
/**
* 包装类型为瓶装
* @author ZSH
*
*/
public class Bottle implements Packing {
@Override
public String pack() {
// TODO Auto-generated method stub
return "Bottle";
}
}
到这里,我们的的包装类型就已经写好了,接下来就是创建汉堡和饮料了,首先是汉堡,创建一个抽象类实现Item:
/**
* 抽象类,汉堡,实现Item
* @author ZSH
*
*/
public abstract class Burger implements Item {
/**
* 汉堡一般用纸装
*/
@Override
public Packing packing() {
return new Wrapper();
}
}
汉堡是用纸包装的,直接写上,然后创建子类蔬菜汉堡和鸡肉汉堡:
/**
* 蔬菜汉堡继承自汉堡,由于父类是实现
* 自Item的并且自身是抽象的,所以要重写父类的方法
* @author ZSH
*
*/
public class VegBurger extends Burger {
@Override
public String name() {
return "VegBurger";
}
@Override
public float price() {
return 25.0f;
}
}
/**
* 和蔬菜汉堡一样,鸡肉汉堡也是一样
* @author ZSH
*
*/
public class ChickenBurger extends Burger {
@Override
public String name() {
return "ChickenBurger";
}
@Override
public float price() {
return 50.0f;
}
}
由于继承的父类实现了Item,子类必须要重写并实现相应的方法(自己不是很懂)。相同的,在饮料创建上是一样的,我就不一一赘述,直接上代码:
父类:
/**
* 冷饮也实现Item
* @author ZSH
*
*/
public abstract class ColdDrink implements Item {
/**
* 冷饮一般用瓶装
*/
@Override
public Packing packing() {
return new Bottle();
}
@Override
public abstract float price();
}
子类:
/**
* 焦炭可乐继承冷饮
* @author ZSH
*
*/
public class Coke extends ColdDrink {
@Override
public String name() {
return "Coke";
}
@Override
public float price() {
return 30.0f;
}
}
/**
* 百事可乐继承冷饮
* @author ZSH
*
*/
public class Pepsi extends ColdDrink {
@Override
public String name() {
return "Pepsi";
}
@Override
public float price() {
return 35.0f;
}
}
然后创建一个Meal类,作用类似于就是将价钱算出,并显示套餐内容:
/**
* 返回一个Meal对象 用来展现套餐里面的食物
* @author ZSH
*
*/
public class Meal {
private List<Item> items = new ArrayList<>();
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.name());
System.out.println(item.packing().pack());
System.out.println(item.price());
}
}
}
接着,创建MealBuilder,设置套餐:
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 ChickenBurger());
meal.addItem(new Pepsi());
return meal;
}
}
到这里基本就大功告成了,下面编写测试类:
/**
* 测试类
* @author ZSH
*
*/
public class BuilderPatternDemo {
public static void main(String[] args) {
//首先获取到食物工厂,决定要哪一份
MealBuilder mealBuilder = new MealBuilder();
//调用方法,获取Vegburger,返回一个Meal对象
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("\n\nNon-Veg Meal");
nonVegMeal.showItems();
System.out.println("Total Cost: " + nonVegMeal.getCost());
}
}
最后的输出结果:
Veg Meal
VegBurger
Wrapper
25.0
Coke
Wrapper
30.0
Total Cost: 55.0
Non-Veg Meal
ChickenBurger
Wrapper
50.0
Pepsi
Wrapper
35.0
Total Cost: 85.0