一、定义
定义(百度百科):建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
核心有两点:
1、将创建对象的代码,过程与对象分离。
2、可构建出不同的对象。
二、UML
如图,定义了各种菜品,建造者模式相关的为图中框出来的部分,Meal套餐中可以有各种菜品,真正去构建Meal的是在MealABuilder中去进行构建(实现了定义中核心点1,Meal与构建Meal代码分离)。使用不同的建造器,构建出来的菜单是不一样的(实现了定义中核心点2),Director是构建的指挥类,负责控制菜单对象的生成过程。
是不是看着还不太理解各类的作用??别急,接着往下看例子.....
三、代码实现
我们来看下创建外卖订单怎么来抽象,并保证我们的订单一定预定了米饭。
1、我们先定义各种菜品及套餐类,假设可以点的菜为:米饭、红烧鱼、土豆、番茄炒鸡蛋
package com.design.builder;
public abstract class Food {
private String foodName;
private int price;
public Food(String foodName, int price) {
this.foodName = foodName;
this.price = price;
}
public String getFoodName() {
return foodName;
}
public void setFoodName(String foodName) {
this.foodName = foodName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public void showTheFood(){
System.out.println("食物:"+foodName+",价格:"+price);
}
}
复制代码
package com.design.builder;
/**
* 米饭
*/
public class Rice extends Food {
public Rice() {
super("米饭", 3);
}
}
复制代码
package com.design.builder;
public class Fish extends Food {
public Fish() {
super("红烧鱼", 20);
}
}
复制代码
package com.design.builder;
/**
* 土豆
*/
public class Potato extends Food{
public Potato() {
super("土豆", 8);
}
}
复制代码
package com.design.builder;
/**
* 番茄炒蛋
*/
public class TomatoWithEgg extends Food{
public TomatoWithEgg() {
super("番茄炒蛋", 15);
}
}复制代码
package com.design.builder;
/**
套餐类
*/
public class Meal {
private Rice rice;
private Fish fish;
private Potato potato;
private TomatoWithEgg tomatoWithEgg;
public Rice getRice() {
return rice;
}
public void setRice(Rice rice) {
this.rice = rice;
}
public Fish getFish() {
return fish;
}
public void setFish(Fish fish) {
this.fish = fish;
}
public Potato getPotato() {
return potato;
}
public void setPotato(Potato potato) {
this.potato = potato;
}
public TomatoWithEgg getTomatoWithEgg() {
return tomatoWithEgg;
}
public void setTomatoWithEgg(TomatoWithEgg tomatoWithEgg) {
this.tomatoWithEgg = tomatoWithEgg;
}
public void showMeal(){
System.out.println("=========套餐===========");
if (rice != null){
rice.showTheFood();
}
if(fish != null){
fish.showTheFood();
}
if(potato != null){
potato.showTheFood();
}
if(tomatoWithEgg != null){
tomatoWithEgg.showTheFood();
}
System.out.println("========套餐结束=========");
}
}
复制代码
2、构建类,即创建套餐的类,在定义中,我们知道对象的创建是与对象分离的。于是我们就在该构建类中来定义套餐对象。
1)、先定义接口,构建类中,我们定义了增加米饭,增加菜的方法。
package com.design.builder;
//构造者抽象类
public interface IBuilder {
//給套餐增加米饭
public void addRice();
//給套餐增加菜
public void addFood();
public Meal build();
}
复制代码
2)、构建类
package com.design.builder;
/**
* 套餐A建造者
*/
public class MealABuilder implements IBuilder{
private Meal meal;
public MealABuilder() {
meal = new Meal();
}
@Override
public void addRice(){
meal.setRice(new Rice());
}
//点菜的方法
@Override
public void addFood() {
//套餐A,红烧鱼,爆炒土豆
meal.setPotato(new Potato());
meal.setFish(new Fish());
}
@Override
public Meal build(){
return meal;
}
}
复制代码
package com.design.builder;
/**
* 套餐B建造者
*/
public class MealBBuilder implements IBuilder {
private Meal meal;
public MealBBuilder() {
meal = new Meal();
}
@Override
public void addRice() {
meal.setRice(new Rice());
}
//点菜的方法
@Override
public void addFood() {
//套餐B,西红柿炒鸡蛋,红烧鱼
meal.setTomatoWithEgg(new TomatoWithEgg());
meal.setFish(new Fish());
}
@Override
public Meal build() {
return meal;
}
}复制代码
3、指挥类,用来定义构建的过程,套餐构建为:增加米饭,增加菜。
package com.design.builder;
public class Director {
private IBuilder mealBuilder;
public Director(IBuilder mealBuilder){
this.mealBuilder = mealBuilder;
}
/**
* 构建套餐A
*/
public void buildMeal(){
mealBuilder.addRice();
mealBuilder.addFood();
}
}
复制代码
4、测试
package com.design.builder;
import javafx.util.Builder;
public class TestMain {
public static void main(String[] args) {
MealBuilder builder = new MealBuilder();
Director director = new Director(builder);
director.buildMealA();
builder.build().showMeal();
MealBuilder builder2 = new MealBuilder();
Director director2 = new Director(builder2);
director2.buildMealB();
builder2.build().showMeal();
}
}
复制代码
执行结果
四、总结
建造者模式,适用于建造复杂对象。与静态工厂方法模式相比,建造者模式更注重零件装配,主要目的是通过组装零配件而产生一个新产品。如上,米饭、菜品相当与菜单类的零配件,通过往菜单中增加米饭,菜来构建一个菜单。
看到一篇文章,里面对建造者模式、静态工厂方法模式的区别描述得比较巧妙,这里引用一下:
如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车
优点:
1、使用建造者模式中客户端不需要知道创建对象的构造过程。
2、产品创建与产品本身解耦,相同的创建过程可创建不同对象。(Director中创建菜单的步骤都是一样的,都是增加米饭,增加菜品)。
3、扩展性好,要新增新的套餐,只需新增Builder(建造器)即可。
缺点:
1、如果要创建的对象可变因素较多,则可能有很多种套餐可能,需要定义的建造器较多。