門面模式
阿新 • • 發佈:2018-10-04
多個 div 常用 some 代碼 問題: 相對 源碼 靠譜
門面模式,也叫外觀模式,是一種比較常用的封裝模式,定義如下:要求一個子系統的外部與其內部的通信必須通過一個統一的對象進行,門面模式提供了一個高層次的接口,使得子系統更易於使用。門面對象是通往外界子系統內部的唯一通道,我們先明確下門面模式的角色:
- Facade門面角色:客戶端可以調用這個角色的方法,此角色知曉子系統的所有功能和職責。一般情況下,本角色會將所有客戶端發來的請求委派到響應的子系統,也就是該角色沒有實際的業務邏輯,只是一個委托類。
- subsystem子系統:可以有一個或多個子系統,每個子系統都不是一個單獨的類,而是一個類的集合,子系統並不知道門面的存在,對於子系統而言,門面就是一個客戶端而已。
下面看一個門面模式的通用代碼示例:
//子系統 public class ClassA{ public void doSomethingA(){ } } public class ClassB{ public void doSomethingB(){ } } public class ClassC{ public void doSomethingC(){ } } //門面對象 public class Facade{ //被委托的對象 private ClassA a = new ClassA(); private ClassB b = newClassB(); private ClassC c = new ClassC(); //提供給外部訪問的方法 public void methodA(){ this.doSomethingA(); } public void methodB(){ this.doSomethingB(); } public void methodC(){ this.doSomethingC(); } }
門面模式優點:
- 減少系統間依賴
- 提高了靈活性:不管子系統內部如何變化,只要不影響門面對象,可以自由行動。
- 提高了安全性:想讓外界訪問子系統的哪些業務就開通哪些邏輯,不在門面上開通的方法,外界就不能訪問。
門面模式缺點:
- 門面模式最大缺點就是不符合開閉原則,對修改關閉,對擴展開放,一旦系統投產後發現問題,繼承和覆寫都不頂用,只能修改門面對象源碼,風險較大,需要謹慎對待。
使用場景:
- 為一個復雜的模塊或子系統提供一個對外訪問的接口
- 子系統相對獨立--外界訪問只需要黑箱操作即可
- 預防低水平人員帶來的風險擴散
註意事項:
1.一個子系統可以有多個門面
一般情況下,一個門面只有一個門面就夠了,但在一下情況下可以有多個門面,
- 門面已經龐大到不能忍受的程度:按照功能拆分為多個門面是個不錯的原則
- 子系統提供不同的訪問路徑
2.門面不參與子系統的業務邏輯
以上述通用源代碼為例,把門面類上的methodC改一下,讓他先調用ClassA的方法,再調用ClassC的方法:
//修改門面 public class Facade{ //被委托的對象 private ClassA a = new ClassA(); private ClassB b = new ClassB(); private ClassC c = new ClassC(); //提供給外部訪問的方法 public void methodA(){ this.a.doSomethingA(); } public void methodB(){ this.b.doSomethingB(); } //加入業務邏輯 public void methodC(){ this.a.doSomethingA(); this.c.doSomethingC(); } }
上述門面對象中已經參與了業務邏輯,這樣設計是非常不靠譜的,為什麽呢?因為門面對象只是提供了一個訪問子系統的一個路徑而已,不應該參與具體的業務邏輯,否則會出現顛倒依賴的問題:子系統必須依賴門面才能訪問,這是一個設計的錯誤!不僅違反單一職責原則,同時也破壞了系統的封裝性。那麽應該怎麽處理呢?建立一個封裝類,封裝完畢後提供給門面對象。我們先建立一個封裝類:
//封裝類 public class context{ //委托處理 private ClassA a = new ClassA(); private ClassC c = new ClassC(); //業務邏輯、復雜的計算 public void complexMethod(){ this.a.methodA(); this.c.methodC(); } } //門面類 public class Facade { //被委托的對象 private ClassA a = new ClassA(); private ClassB b = new ClassB(); private Context context = new Context(); //提供給外部訪問的方法 public void methodA(){ this.a.doSomethingA(); } public void methodB(){ this.b.doSomethingB(); } public void methodC(){ this.context.complexMethod(); } }
這樣一次封裝後,門面對象就不會參與到業務邏輯裏了,在門面模式中,門面角色應該是穩定的,他不應該經常變化,一旦系統運行就不應該再被改變,它是子系統對外提供的接口,變來變去還怎麽保證其他模塊的穩定呢?所有的變化都應該被封裝在子系統內部,無論怎麽變化,在外界看到還是同一個方法,同一個門面,這才是最好的架構。
門面模式