设计模式之建造者模式

一、定义

你有没有出现过点了个外卖,结果外卖送过来的时候发现忘了点个米饭。结果只能屁颠屁颠再点一份米饭,再等一个小时。你有没有经历炒好了所有的菜之后,发现你还没有煮饭的尴尬?来看看建造者模式是怎么来创建对象的。

定义(百度百科):建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

核心有两点

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、如果要创建的对象可变因素较多,则可能有很多种套餐可能,需要定义的建造器较多。


转载于:https://juejin.im/post/5ced0234e51d45777540fd3a

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值