設計模式之建造者模式

1、定義

你有沒有出現過點了個外賣,結果外賣送過來的時候發現忘了點個米飯。結果只能屁顛屁顛再點一份米飯,再等一個小時。你有沒有經歷炒好了全部的菜以後,發現你尚未煮飯的尷尬?來看看建造者模式是怎麼來建立對象的。

定義(百度百科):建造者模式是設計模式的一種,將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。java

核心有兩點設計模式

一、將建立對象的代碼,過程與對象分離。bash

二、可構建出不一樣的對象。ide

2、UML

如圖,定義了各類菜品,建造者模式相關的爲圖中框出來的部分,Meal套餐中能夠有各類菜品,真正去構建Meal的是在MealABuilder中去進行構建(實現了定義中核心點1,Meal與構建Meal代碼分離)。使用不一樣的建造器,構建出來的菜單是不同的(實現了定義中核心點2),Director是構建的指揮類,負責控制菜單對象的生成過程。測試

是否是看着還不太理解各種的做用??別急,接着往下看例子.....ui



3、代碼實現

咱們來看下建立外賣訂單怎麼來抽象,並保證咱們的訂單必定預約了米飯。this

一、咱們先定義各類菜品及套餐類,假設能夠點的菜爲:米飯、紅燒魚、土豆、番茄炒雞蛋spa

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("========套餐結束=========");

    }
}
複製代碼

二、構建類,即建立套餐的類,在定義中,咱們知道對象的建立是與對象分離的。因而咱們就在該構建類中來定義套餐對象。設計

1)、先定義接口,構建類中,咱們定義了增長米飯,增長菜的方法。3d

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;
    }
}複製代碼

三、指揮類,用來定義構建的過程,套餐構建爲:增長米飯,增長菜。

package com.design.builder;

public class Director {

    private IBuilder mealBuilder;

    public Director(IBuilder mealBuilder){
        this.mealBuilder = mealBuilder;
    }

    /**
     * 構建套餐
     */
    public void buildMeal(){
        mealBuilder.addRice();
        mealBuilder.addFood();
    }

}

複製代碼

四、測試

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();
    }
}
複製代碼

執行結果



4、總結

建造者模式,適用於建造複雜對象。與靜態工廠方法模式相比,建造者模式更注重零件裝配,主要目的是經過組裝零配件而產生一個新產品。如上,米飯、菜品至關與菜單類的零配件,經過往菜單中增長米飯,菜來構建一個菜單。

看到一篇文章,裏面對建造者模式、靜態工廠方法模式的區別描述得比較巧妙,這裏引用一下:

若是將抽象工廠模式當作汽車配件生產工廠,生產一個產品族的產品,那麼建造者模式就是一個汽車組裝工廠,經過對部件的組裝能夠返回一輛完整的汽車

優勢:

一、使用建造者模式中客戶端不須要知道建立對象的構造過程。

二、產品建立與產品自己解耦,相同的建立過程可建立不一樣對象。(Director中建立菜單的步驟都是同樣的,都是增長米飯,增長菜品)。

三、擴展性好,要新增新的套餐,只需新增Builder(建造器)便可。

缺點:

一、若是要建立的對象可變因素較多,則可能有不少種套餐可能,須要定義的建造器較多。

相關文章
相關標籤/搜索