1.前言
代理和裝飾模式都是對單個對象的封裝亮航,不熟悉的朋友可以到設(shè)計模式文集中查看一下将塑。若將這個對象擴展一下缀辩,讓它成為具有某種業(yè)務(wù)功能的模塊劲件,甚至系統(tǒng)畔规,會如何棠涮?對箫老,說到底昔榴,它仍是一個對象妓肢。不過這個對象在工作時捌省,內(nèi)部的子對象會相互調(diào)用,完成數(shù)據(jù)的傳遞碉钠,共同支持著整個大的對象纲缓。
2.概念
外觀模式要求一個子系統(tǒng)的外部與其內(nèi)部的通信必須通過一個統(tǒng)一的對象進行。目的很簡單喊废,就是為了對外隱藏子系統(tǒng)的具體實現(xiàn)祝高、隔離變化。
因為子系統(tǒng)的功能可能一開始就比較復(fù)雜污筷,又或者隨著使用而變得復(fù)雜褂策。一旦復(fù)雜,根據(jù)單一職責原則颓屑,將拆分出更多斤寂、更小的類來負責其中的一個方面。對于使用者而言揪惦,必須了解到每個類的作用才能靈活使用遍搞,這無疑增加了學(xué)習(xí)的成本。所以直接提供子系統(tǒng)功能的調(diào)用器腋,拒絕對其內(nèi)部的訪問溪猿。
若系統(tǒng)具有層次結(jié)構(gòu)钩杰,那么每一層都相當于是子系統(tǒng),并且之間相互依賴诊县。當某一層需要改變或替換時讲弄,將會影響到相關(guān)的層級,這無疑增加了維護的難度依痊”艹可在每層的入口提供調(diào)用的抽象,將依賴關(guān)系進行隔離胸嘁。
3.場景
現(xiàn)在的汽車是個很復(fù)雜的系統(tǒng)瓶摆,由不少小的子系統(tǒng)組成,其中動力系統(tǒng)包含發(fā)動機性宏,運行系統(tǒng)包含輪胎群井。但作為司機,若想開動汽車毫胜,不需要知道如何啟動發(fā)動機书斜,再將動力傳輸給輪胎,這一切相應(yīng)的系統(tǒng)內(nèi)部會處理酵使。若想更換不同類型的輪胎菩佑,也不需要改造汽車,它們之間不是直接相連凝化,而是通過標準的軸承相連稍坯。
4.寫法
子系統(tǒng)內(nèi)部各層級間調(diào)用的抽象,以及對應(yīng)的具體實現(xiàn)搓劫。
public interface Engine {
void startUp();
}
public class Benz implements Engine {
@Override
public void startUp() {
System.out.println("發(fā)動奔馳引擎");
}
}
public interface Tyre {
void roll();
}
public class Giti implements Tyre {
@Override
public void roll() {
System.out.println("使用佳通輪胎");
}
}
public class Michelin implements Tyre {
@Override
public void roll() {
System.out.println("使用米其林輪胎");
}
}
任何一個系統(tǒng)相對于使用者所在的系統(tǒng)瞧哟,也是個子系統(tǒng),它與內(nèi)部系統(tǒng)的關(guān)系是具有層級的枪向。通過抽象的接口調(diào)用勤揩,可以增加維護的靈活性,減少對自己的影響秘蛔。
// 1.聲明(子)系統(tǒng)對外的對象
public class Car {
// 2.列出包含的子系統(tǒng)
private Engine mEngine;
private Tyre mTyre;
public Car(Engine engine, Tyre tyre) {
mEngine = engine;
mTyre = tyre;
}
// 3.設(shè)置子系統(tǒng)的變化
public void setmTyre(Tyre tyre) {
mTyre = tyre;
}
// 4.對外展示功能的調(diào)用
public void drive() {
startUp();
roll();
}
// 5.內(nèi)部具體實現(xiàn)
private void startUp() {
mEngine.startUp();
}
private void roll() {
mTyre.roll();
}
}
提供一個統(tǒng)一的高層接口陨亡,使功能的調(diào)用簡單明確,降低用戶使用成本深员,也對用戶屏蔽許多不需要知道的細節(jié)负蠕。
public class Client {
public static void main(String[] args) {
// 1.創(chuàng)建子系統(tǒng)實例
Car mCar = new Car(new Benz(), new Giti());
// 2.調(diào)用對外功能接口
mCar.drive();
// 3.子系統(tǒng)內(nèi)部改變
mCar.setmTyre(new Michelin());
mCar.drive();
}
}
5.總結(jié)
外觀模式就是最常用的封裝,將完整的倦畅、復(fù)雜的功能作為一個對象封裝起來遮糖。由于用戶不知道細節(jié),降低了使用的耦合度叠赐;又將復(fù)雜的功能邏輯放在內(nèi)部欲账,降低了使用的難度屡江。可能的缺點便是赛不,通過接口降低內(nèi)部邏輯的耦合惩嘉,便于維護的同時,增加了過多的代碼踢故。