7,建造者模式-麦当劳套餐

329 阅读5分钟

一,前言

开始我们按照由易到难顺序进入,现在需要按照设计模式的分类进行了
创建型模式包含:工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式
前篇完成了工厂模式专题了,包括简单工程,工厂方法模式,抽象工厂模式
下面两篇我们开始建造者模式和原型模式,这样就完成了创建型模式这一类的学习

二,建造者模式

建造者模式:将一个复杂的对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示

我们以一个麦当劳套餐的例子来说明建造者模式
麦辣鸡腿堡套餐:麦辣鸡腿汉堡+薯条+可乐
板烧鸡腿堡套餐:板烧鸡腿汉堡+土豆泥+热橙汁(板烧鸡腿汉堡貌似不是这个组合...)

分析相同点和不同点
相同点:套餐产品类型组合都是汉堡+小吃+饮料
不同点:套餐具体产品不同

按照建造者模式的来实现创建套餐的过程:
创建建造者接口(抽象类)规定产品组成(组装步骤):主食+小吃+饮料
实现建造者接口的具体抽象类:麦辣鸡腿堡套餐,板烧鸡腿堡套餐

三,建造者模式的代码实现

代码结构

1,套餐类:规定包含主食+小吃+饮料的套餐类型

package com.brave.food.builder.food;

/**
 * 套餐类
 *  规定了套餐组成部分:主食+小吃+饮料
 * 
 * @author Brave
 *
 */
public class Combo {

    private String comboName;               // 套餐名称
    private PrincipalFood principalFood;    // 主食
    private Snack snack;                    // 小吃
    private Drink drink;                    // 饮料

    public String getComboName() {
        return comboName;
    }

    public void setComboName(String comboName) {
        this.comboName = comboName;
    }

    public PrincipalFood getPrincipalFood() {
        return principalFood;
    }

    public void setPrincipalFood(PrincipalFood principalFood) {
        this.principalFood = principalFood;
    }

    public Snack getSnack() {
        return snack;
    }

    public void setSnack(Snack snack) {
        this.snack = snack;
    }

    public Drink getDrink() {
        return drink;
    }

    public void setDrink(Drink drink) {
        this.drink = drink;
    }

    public String show() {
        return "套餐名称:" + comboName + ",包含: 主食-" + principalFood.getName() + ", 小吃-" + snack.getName() + ", 饮料-" + drink.getName();
    }

}

2,创建抽象建造者,规定产品的组成或组装步骤

package com.brave.food.builder;

import com.brave.food.builder.food.Combo;

/**
 * Builder建造者抽象类
 *  规定了产品的建造有哪些步骤和方法,但不规定顺序
 * 
 *  建造者模式:将一个复杂的对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示
 * 
 * @author Brave
 *
 */
public abstract class Builder {

    public abstract void buildComboName();
    public abstract void buildPrincipalFood();
    public abstract void buildSnack();
    public abstract void buildDrink();

    public abstract Combo getCombo();

}

3,继承抽象建造者,创建具体建造者

package com.brave.food.builder;

import com.brave.food.builder.food.Combo;
import com.brave.food.builder.food.Drink;
import com.brave.food.builder.food.PrincipalFood;
import com.brave.food.builder.food.Snack;

/**
 * 麦辣鸡腿汉堡套餐建造者(具体Builder类)
 *  对套餐的各个步骤确定具体产品
 * 
 * @author Brave
 *
 */
public class ComboBuilderA extends Builder {

    private Combo product = new Combo();

    @Override
    public void buildComboName() {
        product.setComboName("麦辣鸡腿堡套餐");
    }

    @Override
    public void buildPrincipalFood() {
        PrincipalFood principalFood = new PrincipalFood();
        principalFood.setName("麦辣鸡腿堡");
        product.setPrincipalFood(principalFood);
    }

    @Override
    public void buildSnack() {
        Snack snack = new Snack();
        snack.setName("薯条");
        product.setSnack(snack);
    }

    @Override
    public void buildDrink() {
        Drink drink = new Drink();
        drink.setName("可口可乐");
        product.setDrink(drink);
    }

    @Override
    public Combo getCombo() {
        return product;
    }

}
package com.brave.food.builder;

import com.brave.food.builder.food.Combo;
import com.brave.food.builder.food.Drink;
import com.brave.food.builder.food.PrincipalFood;
import com.brave.food.builder.food.Snack;

/**
 * 板烧鸡腿汉堡套餐建造者(具体Builder类)
 *  对套餐的各个步骤确定具体产品
 * 
 * @author Brave
 *
 */
public class ComboBuilderB extends Builder {

    private Combo product = new Combo();

    @Override
    public void buildComboName() {
        product.setComboName("板烧鸡腿堡套餐");
    }

    @Override
    public void buildPrincipalFood() {
        PrincipalFood principalFood = new PrincipalFood();
        principalFood.setName("板烧鸡腿堡");
        product.setPrincipalFood(principalFood);
    }

    @Override
    public void buildSnack() {
        Snack snack = new Snack();
        snack.setName("土豆泥");
        product.setSnack(snack);
    }

    @Override
    public void buildDrink() {
        Drink drink = new Drink();
        drink.setName("热橙汁");
        product.setDrink(drink);
    }

    @Override
    public Combo getCombo() {
        return product;
    }

}

4,创建指挥者类:指挥产品的创建步骤

package com.brave.food.builder;

/**
 * 指挥者类
 *  保证了装配步骤的完整性和正确性
 *  隔离了客户端和具体步骤的依赖,将一个复杂对象的构建和制作过程与这个对象的表示分离
 *  
 * @author Brave
 *
 */
public class Director {

    public void ConstructBuild(Builder builder){

        builder.buildComboName();
        builder.buildPrincipalFood();
        builder.buildSnack();
        builder.buildDrink();

    }
}

5,测试类

package com.brave.food.builder;

import com.brave.food.builder.food.Combo;

public class Client {

    public static void main(String[] args) {

        Director director = new Director();
        Builder builderA = new ComboBuilderA();
        Builder builderB = new ComboBuilderB();

        director.ConstructBuild(builderA);
        Combo comboA = builderA.getCombo();
        System.out.println(comboA.show());

        director.ConstructBuild(builderB);
        Combo comboB = builderB.getCombo();
        System.out.println(comboB.show());

    }

}

打印输出:

套餐名称:麦辣鸡腿堡套餐,包含: 主食-麦辣鸡腿堡, 小吃-薯条, 饮料-可口可乐
套餐名称:板烧鸡腿堡套餐,包含: 主食-板烧鸡腿堡, 小吃-土豆泥, 饮料-热橙汁

四,建造者模式分析

建造者模式属于创建型模式
建造者模式的核心在于,抽象建造者和指挥者这两个类

抽象建造者(Builder)规定了产品的创建步骤
指挥者(Director)确保了产品组装顺序和步骤的完整性

建造者模式隐藏了产品的组装过程
客户端创建产品时,只需传入指挥者对应的建造者类,即可完成对象创建
客户端不需要知道产品的创建过程,更不需要知道创建产品需要依赖的其他组件

依赖倒置:依赖于抽象,不依赖具体
只需要指定创建的类型就可以得到对应的对象,而具体的建造过程和细节被Builder和Director隐藏
开放-封闭原则:
指挥者类是针对抽象建造者进行操作的,使用不同的具体建造者就可以得到不同的产品对象

五,建造者模式与工厂模式的比较

工厂模式和建造者模式的相同点:
    都是创建型模式,最终目的都是得到一个对象
    两者都将对象的创建过程与客户端隔离
工厂模式和建造者模式的不同点:
    1,侧重点不同:
        工厂模式侧重与将对象的实例化延迟到子类进行
        建造者侧重于保持对象建造过程的稳定性
    2,创建对象的表象不同:
        工厂模式创建相同表象的对象(客户端向工厂要指定类型的产品)
        建造者模式创建多种表象的对象(传入相同类型[不同建造者],得到不同产品)