標籤:不同 static 列印 模組 music 通知 com 營業廳 定義
4.1關聯背景故事
去營業廳辦理手機套餐,有以下兩種套餐可以選擇:
1)20元包400條簡訊的套餐;
2)30元包600條簡訊的套餐。
並且兩種套餐都必須開通彩鈴業務。
4.2模式定義
建造者模式(Builder Pattern),在一個軟體系統中,可能會面臨建立一些複雜物件的工作,如果我們使用單一的方法或單一的對象來建立會比較繁瑣,當所建立的複雜物件發生變化時,整個系統就可能面臨劇烈的變化。
為瞭解決這個問題,我們可以將這個複雜物件的建立過程分解成若干個部分,各個子部分用一定的演算法構成。但是,子部分可能會經常發生改變,如何能保證整體建立工作的穩定性呢?這就需要建造者模式的支援了。建造者模式把複雜物件的建立與表示分離,使得同樣的構建過程可以建立不同的表示。
4.3故事中的模式分析
4.3.1角色分析
例子中出現的事物對象有:
1)客戶張三
2)營業廳操作員
3)設定客戶套餐的電腦
4)手機套餐
客戶張三就是最終獲得手機套餐的終端,營業廳操作員相當於一個指導者的身份,只有操作員才知道客戶需要什麼樣的套餐,而電腦充當著一個建造者的角色,電腦通過操作設定客戶的手機套餐,手機套餐就是最終的產品,生產出來給客戶使用。
例子中的各種角色列出如下:
客戶張三——終端需求
營業廳操作員——指導者(通知指導建造者生產什麼樣的手機套餐)
電腦——建造者(建造各種手機套餐)
手機套餐——產品
4.3.2建造者模式的靜態建模
,在建造者工廠中將構建手機套餐對象細化分解成三個過程:構建話費、構建簡訊、構建彩鈴。每一個過程實現的功能很專業化、單一化,三個功能又互不干擾,還有一個功能返回手機套餐執行個體,使構建和表示分離,功能模組之間的耦合度大大降低,模組內部具有很高的內聚度。
4.4模式實現
4.4.1建立產品——手機套餐
package com.demo.builder.model;/** * Created by lsq on 2018/3/14. * 手機套餐類 */public class MobilePackage { //話費 private float money; //簡訊 private int shortInfo; //彩鈴 private String music; public float getMoney() { return money; } public void setMoney(float money) { this.money = money; } public int getShortInfo() { return shortInfo; } public void setShortInfo(int shortInfo) { this.shortInfo = shortInfo; } public String getMusic() { return music; } public void setMusic(String music) { this.music = music; }}
4.4.2建立抽象建造者
1)建造者介面——IMobileBuilder
package com.demo.builder.itf;import com.demo.builder.model.MobilePackage;/** * Created by lsq on 2018/3/14. * 手機套餐建造者 */public interface IMobileBuilder { //建造手機套餐的話費 public void buildMoney(); //建造手機套餐的簡訊 public void buildShortInfo(); //建造手機套餐的彩鈴 public void buildMusic(); //返回建造的手機套餐對象 public MobilePackage getMobilePackage();}
2)抽象建造者——AbstractBasePackage
package com.demo.builder.base;import com.demo.builder.model.MobilePackage;/** * Created by lsq on 2018/3/14. * 抽象建造者 */public abstract class AbstractBasePackage { //手機套餐執行個體變數 protected MobilePackage mobilePackage; public AbstractBasePackage() { this.mobilePackage = new MobilePackage(); }}
4.4.3建立具體建造者
1)具體的建造者——MobileBuilderImpl1
package com.demo.builder.itf;import com.demo.builder.base.AbstractBasePackage;import com.demo.builder.model.MobilePackage;/** * Created by lsq on 2018/3/14. * 套餐1 */public class MobileBuilderImpl1 extends AbstractBasePackage implements IMobileBuilder { //建造手機套餐的話費 public void buildMoney() { this.mobilePackage.setMoney(20.0f); } //建造手機套餐的簡訊 public void buildShortInfo() { this.mobilePackage.setShortInfo(400); } //建造手機套餐的彩鈴 public void buildMusic() { this.mobilePackage.setMusic("我們都一樣"); } //返回建造的手機套餐對象 public MobilePackage getMobilePackage() { return this.mobilePackage; }}
2)具體建造者——MobileBuilderImpl2
package com.demo.builder.itf;import com.demo.builder.base.AbstractBasePackage;import com.demo.builder.model.MobilePackage;/** * Created by lsq on 2018/3/14. * 套餐2 */public class MobileBuilderImpl2 extends AbstractBasePackage implements IMobileBuilder { //建造手機套餐的話費 public void buildMoney() { this.mobilePackage.setMoney(30.0f); } //建造手機套餐的簡訊 public void buildShortInfo() { this.mobilePackage.setShortInfo(600); } //建造手機套餐的彩鈴 public void buildMusic() { this.mobilePackage.setMusic("我們不一樣"); } //返回建造的手機套餐對象 public MobilePackage getMobilePackage() { return this.mobilePackage; }}
4.4.4建立指導者
指導者類含有一個方法,該方法以建造者執行個體對象作為參數,設定客戶話費、簡訊和彩鈴資訊,然後返回手機套餐執行個體。
package com.demo.builder.director;import com.demo.builder.itf.IMobileBuilder;import com.demo.builder.model.MobilePackage;/** * Created by lsq on 2018/3/14. * 手機套餐指導者 */public class MobileDirector { public MobilePackage createMobilePackage(IMobileBuilder mobileBuilder){ if (mobileBuilder != null){ //構建話費 mobileBuilder.buildMoney(); //構建簡訊 mobileBuilder.buildShortInfo(); //構建彩鈴 mobileBuilder.buildMusic(); //返回手機套餐 return mobileBuilder.getMobilePackage(); } return null; }}
4.4.5客戶訂購手機套餐
import com.demo.builder.director.MobileDirector;import com.demo.builder.itf.MobileBuilderImpl1;import com.demo.builder.itf.MobileBuilderImpl2;import com.demo.builder.model.MobilePackage;/** * Created by lsq on 2018/3/13. * */public class MainApp { public static void main(String[] args) { //建立指導者 MobileDirector mobileDirector = new MobileDirector(); //套餐1 MobileBuilderImpl1 mobileBuilderImpl1 = new MobileBuilderImpl1(); //套餐2 MobileBuilderImpl2 mobileBuilderImpl2 = new MobileBuilderImpl2(); printMessage(mobileDirector.createMobilePackage(mobileBuilderImpl1)); printMessage(mobileDirector.createMobilePackage(mobileBuilderImpl2)); } /** * 列印輸出套餐資訊 */ public static void printMessage(MobilePackage mobilePackage){ System.out.println("--話費:"+mobilePackage.getMoney()+"\t簡訊:" +mobilePackage.getShortInfo()+"條\t彩鈴:"+mobilePackage.getMusic()); }}
執行結果:
實現的代碼結構:
從以上的代碼不難看出,其實指導者只是一個中介服務而已,最終還是建造者設定執行個體對象,最後返回給終端客戶,那為什麼還要指導者角色呢?
指導者確實是一個中間的服務,但是其所起的作用是不能小覷的,正是指導者的角色起到了對構建者構建產品過程的封裝,有效減少了用戶端使用構建者構建產品的各個過程。假如一個複雜產品的構建需要十幾個過程甚至更多,如果在用戶端一步一步使用構建者來構建複雜物件,那麼用戶端的複雜程度可想而知,最重要的一點是,用戶端需要的是最終產品,構建過程用戶端是不需要關心的。所以,指導者角色的存在是有一定道理的。
4.6使用場合
1)當產生的產品對象內部具有複雜的結構時;
2)當複雜物件需要與表示分離時,可能需要建立不同的表示時;
3)當需要向用戶端隱藏產品內部結構的表現時。
建造者模式的優點在於其構建和表示的分離,有效地將複雜物件處理過程分解,降低功能模組之間的耦合度,增強模組內部的內聚度,使得其在軟體設計模式中具有極其重要的位置。建造者設計模式的結構4-6所示:
其實,建造者模式可以簡化處理,將指導者角色去掉。4-7所示:
經過以上的內容,你可以這樣簡單地理解建造者模式:在建造者內部存在一個具體產品的對象執行個體,所有的構建功能都是針對這個對象執行個體進行的, 而這個對象執行個體就是我們最終想要的東西或者是該對象執行個體的其他表現形式。這就相當於,先在水缸中存滿足夠的水,等到想喝水的時候不用開啟水龍頭接水喝,直接從缸裡舀水就行。當然,即使水缸中沒有接滿足夠的水(構建對象的各個功能是彼此獨立的),你也還是能喝到水的(構建和表示分離)。
擴充:建造者模式和抽象原廠模式的區別
1)建造者模式著重於分步驟構造一個複雜物件,而抽象原廠模式則著重於多個系列的產品對象即對象族的構造;
2)建造者模式是在最後一步返回具體產品,而抽象原廠模式則是立即返回具體產品。
04-手機套餐:建造者模式