建造者模式
為什么使用及建造者模式
就以《大話設(shè)計模式》中的案例來說吧,中國人做飯,同一個魚香肉絲,不同的廚師做出來就很容易不同。而且有可能這個缺鹽、那個缺醋,怎么么辦呢?可以向麥當(dāng)勞學(xué)習(xí)?;旧先袊柠湲?dāng)勞都是一個口味,為什么?因為麥當(dāng)勞餐飲流程基本上被寫死,這個肉炸幾分鐘,這個餅烤幾分鐘。。。這樣做出來的飯自然味道上都大差不差。因此從麥當(dāng)勞的經(jīng)驗來看,應(yīng)當(dāng)給小廚子定一個做魚香肉絲的流程,一個步驟接著另一個步驟,至于每個步驟具體怎么做,那肯定要靠小廚子自己以免廚師忘記。
而且這還不夠,試想一下我們吃魚香肉絲的場景,經(jīng)常有人對老板說多放點辣、少放點辣之類的、把菜炒老點,這也正常嘛,畢竟每個人的口味不一樣。但如果只寫一個統(tǒng)一的步驟,那么小廚子在做飯的時候就不好控制。怎么辦呢?專門找一個人,就叫他廚師長吧,負責(zé)指揮小廚子們干活,在分配任務(wù)的時候把顧客的特殊需求告訴響應(yīng)的小廚子。并且,因為小廚子手藝不是太好,每人就先做一個固定口味的魚香肉絲。
代碼樣例
我說的比較混亂,結(jié)合和具體的代碼可能會好點:
整體步驟Procedure.java
package builder;
/**
* @author: OnlyOne
* @create: 2020-08-26 18:34
* @description: 做魚香肉絲的整體步驟,抽象建造者類,強制規(guī)定做魚香肉絲有哪些步驟
**/
public abstract class Procedure {
/**
* @description: 第一步:放油
* @author: OnlyOne
* @create: 2020/8/26
* @param: []
* @return void
**/
public abstract void putOil();
/**
* @description: 第二部:放鹽
* @author: OnlyOne
* @create: 2020/8/26
* @param: []
* @return void
**/
public abstract void putSalt();
/**
* @description: 第三部:炒菜
* @author: OnlyOne
* @create: 2020/8/26
* @param: []
* @return void
**/
public abstract void hotVegetables();
/**
* @description: 上菜
* @author: OnlyOne
* @create: 2020/8/26
* @param: []
* @return YuXiangRouSi
**/
public abstract YuXiangRouSi Serve();
}
魚香肉絲:YuXiangRouSi.java
package builder;
import java.util.ArrayList;
import java.util.List;
/**
* @author: OnlyOne
* @create: 2020-08-26 18:29
* @description: 產(chǎn)品類,一個產(chǎn)品分為A,B兩部分
**/
public class YuXiangRouSi {
List<String> steps = new ArrayList<String>();
public void add(String step) {
steps.add(step);
}
public void show() {
System.out.println("這盤菜的制作過程:");
for (String step :
steps) {
System.out.println(step);
}
}
}
廚師長:HeadCooker.java
package builder;
/**
* @author: OnlyOne
* @create: 2020-08-26 18:42
* @description: 指揮者類,廚師長,根據(jù)顧客的不同需求做不同版本的魚香肉絲
**/
public class HeadCooker {
/**
* @description: 廚師長指揮小廚子們做飯
* @author: OnlyOne
* @create: 2020/8/26
* @param: [procedure]
* @return void
**/
public void direct(Procedure procedure) {
//第一步,放油
procedure.putOil();
//第二部,放鹽
procedure.putSalt();
//第三部,炒菜
procedure.hotVegetables();
//上菜
procedure.Serve();
}
}
小廚子A:CookerA.java
package builder;
/**
* @author: OnlyOne
* @create: 2020-08-26 18:38
* @description: 具體建造者類,小廚子A,專門做魚香肉絲清淡版,少油、少鹽、菜生
**/
public class CookerA extends Procedure {
private YuXiangRouSi yuXiangRouSi = new YuXiangRouSi();
/**
* @return void
* @description: 第一步:放油
* @author: OnlyOne
* @create: 2020/8/26
* @param: []
**/
@Override
public void putOil() {
yuXiangRouSi.add("放入少量的油");
}
/**
* @return void
* @description: 第二部:放鹽
* @author: OnlyOne
* @create: 2020/8/26
* @param: []
**/
@Override
public void putSalt() {
yuXiangRouSi.add("放入少量的鹽");
}
/**
* @return void
* @description: 第三部:炒菜
* @author: OnlyOne
* @create: 2020/8/26
* @param: []
**/
@Override
public void hotVegetables() {
yuXiangRouSi.add("小火翻炒");
}
/**
* @return YuXiangRouSi
* @description: 上菜
* @author: OnlyOne
* @create: 2020/8/26
* @param: []
**/
@Override
public YuXiangRouSi Serve() {
return yuXiangRouSi;
}
}
小廚子B:CookerB.java
package builder;
/**
* @author: OnlyOne
* @create: 2020-08-26 18:38
* @description: 具體建造者類,小廚子B,專門做魚香肉絲爽辣版,多油、多鹽,菜熟
**/
public class CookerB extends Procedure {
private YuXiangRouSi yuXiangRouSi = new YuXiangRouSi();
/**
* @return void
* @description: 第一步:放油
* @author: OnlyOne
* @create: 2020/8/26
* @param: []
**/
@Override
public void putOil() {
yuXiangRouSi.add("放入大量的油");
}
/**
* @return void
* @description: 第二部:放鹽
* @author: OnlyOne
* @create: 2020/8/26
* @param: []
**/
@Override
public void putSalt() {
yuXiangRouSi.add("放入大量的鹽");
}
/**
* @return void
* @description: 第三部:炒菜
* @author: OnlyOne
* @create: 2020/8/26
* @param: []
**/
@Override
public void hotVegetables() {
yuXiangRouSi.add("大火翻炒");
}
/**
* @return YuXiangRouSi
* @description: 上菜
* @author: OnlyOne
* @create: 2020/8/26
* @param: []
**/
@Override
public YuXiangRouSi Serve() {
return yuXiangRouSi;
}
}
顧客:Main.java
package builder;
/**
* @author: OnlyOne
* @create: 2020-08-26 18:43
* @description: 客戶端
**/
public class Main {
public static void main(String[] args) {
HeadCooker headCooker = new HeadCooker();
Procedure cookerA = new CookerA();
Procedure cookerB = new CookerB();
// 顧客點餐了
System.out.println("顧客一:來一份清淡版的魚香肉絲");
// 廚師長指揮
headCooker.direct(cookerA);
// 上菜
YuXiangRouSi yuXiangRouSiA = cookerA.Serve();
// 查看做飯步驟
yuXiangRouSiA.show();
System.out.println("**************************************");
System.out.println("顧客二:來一份爽辣版的魚香肉絲");
headCooker.direct(cookerB);
YuXiangRouSi yuXiangRouSiB = cookerB.Serve();
yuXiangRouSiB.show();
}
}
運行結(jié)果:
個人思考
在使用建造者模式的時候,我明顯感覺建造者模式與之前學(xué)過的一種設(shè)計模式很像,即模板方法。
模板方法是在抽象類中定義步驟,讓子類去繼承,關(guān)鍵之處在于相同的方法就在抽象類中實現(xiàn),而不相同的方法,就讓其子類各自實現(xiàn)。相對而言比較簡單
建造者模式與,模板方法很想,我認為它是在模板方法的基礎(chǔ)上增加了一個Director(指揮者),這個Director可以設(shè)置步驟的執(zhí)行順序。
目前也是剛剛接觸建造者模式,對其理解還比較膚淺,甚至有些地方理解錯誤。如果有哪里理解不到位的地方,還請指出。收到后必定會在第一時間進行改正,本篇博客也會持續(xù)更新,有新的理解會及時補充
本文純原創(chuàng),寫作不易,如果了幫到您,請點贊、轉(zhuǎn)發(fā)、收藏!杜絕抄襲,轉(zhuǎn)載請注明來源!