所有設計模式傳送門
一個大的系統一般都由若干個子系統構成,每個子系統包含多個類,這些類協同合作爲用戶提供所需要的功能。一個客戶程序中的某個類的實例如果直接和子系統的多各類的實例打交道完成某項任務,就使客戶程序中的類和子系統有過多的依賴關係。
比如,郵政系統郵寄包裹的子系統包含Check、Weight和Transport類。Check類的實例負責對包裹進行安全檢查,Weight類的實例負責根據包裹的重量計算郵資,Transport類的實例負責爲包裹負責運輸工具。一個要郵寄包裹的用戶若直接和負責郵寄包裹的類的子系統打交道,就必須先進行Check,然後在進行Weight,最後進行Transport,這就是的用戶非常不方便。
外觀模式簡化用戶和子系統進行交互的成熟模式,外觀模式的關鍵是爲子系統提供一個稱作外觀的類,該外觀類的實例負責和子系統中類的實例進行打交道。當用戶想要和子系統若干類的實例進行打交道時,可以代替的和子系統的外觀類的實例打交道。
比如,對於前面敘述的郵寄包裹的子系統,可以爲其提供一個稱作ServerForClient的外觀類,當用戶想要郵寄包裹時,可以直接和ServerForClient的實例打交道,用戶不必瞭解郵寄包裹的子系統中類的細節。
包含角色:
1、子系統(Subsystem): 子系統時若干個類的集合,這些類的實例協同合作爲用戶提供所需要的功能,子系統中任何類都不包含外觀類的實例引用。
2、外觀(Facade): 外觀是一個類,該類包含子系統中全部或者部分類的實例引用,當用戶想要和子系統中的若干個類的實例打交道時,可以代替的和子系統的外觀類的實例打交道。
優點:
1、使客戶和子系統中的類無耦合,並且子系統使用起來更加方便。
2、外觀只是提供一個更加簡潔的界面,並不影響用戶直接使用子系統中的類。
3、子系統中任何類對其方法的內容進行修改,並不影響外觀類的代碼。
適用情景:
1、對於一個複雜的子系統,需要爲用戶提供一個簡單的交互操作。
2、不希望客戶代碼和子系統中的類有耦合,以便提高子系統的獨立性和可移植性。
3、當整個系統需要構建一個層次結構的子系統,不希望這些子系統相互直接的交互。
簡單例子:報社的廣告有三個類CheckWord,Charge和TypeSeting類,各個類的職責如下:
1、CheckWord的實例負責檢查廣告內容包含字符的個數;
2、Charge類的實例負責計算費用;
3、TypeString類的實例負責排版
現在使用外觀模式簡化用戶和上述子系統所進行的交互。比如一個用戶想要在報社上登廣告,那麼用戶只需要將廣告的內容交給子系統的外觀實例即可,外觀的實例將負責和子系統中的類的實例進行交互完成用戶所指派的任務。
/**
* 子系統之Charge
*/
public class Charge {
public final int basicCharge = 12;
CheckWord checkWord;
public Charge(CheckWord checkWord){
this.checkWord = checkWord;
}
public void giveCharge(){
int charge = checkWord.getAmount() * basicCharge;
System.out.println("廣告費用:"+charge+"元");
}
}
/**
* 子系統之CheckWord
*/
public class CheckWord {
public final int baseAmount = 85;
int amount;
String advertisement;
public CheckWord(String advertisement){
this.advertisement = advertisement;
}
public void setChargeAmount(){
amount = advertisement.length() + baseAmount; //計算出付費字符數目
}
public int getAmount(){
return amount;
}
}
/**
* 子系統之TypeString
*/
public class TypeString {
String advertisement;
public TypeString(String advertisement){
this.advertisement = advertisement;
}
public void typeString(){
System.out.println("廣告排版格式:");
System.out.println("************");
System.out.println(advertisement);
System.out.println("************");
}
}
/**
* 外觀類
* 該類的實例包含TypeString、Charge、CheckWord的類的實例的引用。
*/
public class ClientServerFacade {
private CheckWord checkWord;
private Charge charge;
private TypeString typeString;
String advertisement;
public ClientServerFacade(String advertisement){
this.advertisement = advertisement;
checkWord = new CheckWord(advertisement);
charge = new Charge(checkWord);
typeString = new TypeString(advertisement);
}
public void doAdvertisement(){
checkWord.setChargeAmount();
charge.giveCharge();
typeString.typeString();
}
}
/**
* 啓動器類
*/
public class Application {
public static void main(String[] args) {
ClientServerFacade facade;
String clientAdvertisement = "華碩A501L電腦,價格4999,聯繫電話:95279527";
facade = new ClientServerFacade(clientAdvertisement);
facade.doAdvertisement();
}
}
輸出結果: