設計模式-結構模式之Facade

更多請移步: 我的博客

目的

Facade是結構模式的一種,它讓你可以爲一個複雜的系統,類庫或者框架提供一個簡單的接口。

問題

想象一下,代碼必須和一大堆複雜的框架或者類庫協作。你必須手動實力話這些對象,跟蹤依賴,正確的順序關係等等。

最後,你的業務邏輯類會和第三方類庫的實現緊密耦合。這些代碼難以理解和維護。

解決

門面是一個類,它爲一個包含很多類的複雜子系統提供一個簡單的接口。相對直接調用子系統而言,門面提供有限的功能。它僅提供客戶端關心的那些特性。

當你在使用一個擁有很多模塊的的複雜類庫,但是你只用到其中一部分功能時,使用門面模式就顯得很便利。

比如,一個上傳短視頻到Youtube傷的app使用了一個專業的視頻轉換類庫。但是它真正需要的只是一個擁有encode(filename,format)方法的類。創建這種類之後,你變有了第一個門面。

現實世界的類比

電話下單

當你用電話向一個商店下單時,話務員就是所有服務和部門的門面。他或者她提供了下單,支付,配送的簡單接口。

結構

structure

  1. Facade(門面)爲訪問子系統的特定功能提供方便。它知道怎樣引導客戶的請求和怎樣爲所有moving parts做準備。

  2. Additional facades用來隔離功能和阻止源門面變成另外一個複雜結構。Additional facades也可以被客戶端或者其他門面使用。

  3. Complex subsystem(複雜的子系統)包含很多類。爲了讓他們做一些有意義的事情,你必須知道它的實現細節,初始化順序等很多事情。
    注意:子系統並不關心門面的存在,它直接和其他模塊協作。

  4. Client使用門面代替直接調用子系統對象。

僞代碼

在這個例子中,門面簡化了和一個複雜視頻轉換框架的協作。

門面是一個單獨的類,它提供一個公開的方法來處理框架複雜的配置並返回一個正確的格式。

通過這種方式,門面模式保證客戶端代碼簡單、乾淨、可靠。

// Some classes of a complex 3rd-party video conversion framework. We don't
// control that code, therefore can't simplify it.

class VideoFile
// ...

class OggCompressionCodec
// ...

class MPEG4CompressionCodec
// ...

class CodecFactory
// ...

class BitrateReader
// ...

class AudioMixer
// ...


// To defeat the complexity, we create a Facade class, which hides all of the
// framework's complexity behind a simple interface. It is a trade-off between
// functionality and simplicity.
class VideoConvertor is
    method convertVideo(filename, format):File is
        file = new VideoFile(filename)
        sourceCodec = new CodecFactory.extract(file)
        if (format == "mp4")
          distinationCodec = new MPEG4CompressionCodec()
        else
          distinationCodec = new OggCompressionCodec()
        buffer = BitrateReader.read(filename, sourceCodec);
        result = BitrateReader.convert(buffer, distinationCodec);
        result = (new AudioMixer()).fix(result);
        return new File(result)

// Application classes don't depend on a billion classes provided by the complex
// framework. Also, if you happen to decide to switch framework, you will only
// need to rewrite the facade class.
class Application is
    method main() is
        convertor = new VideoConvertor();
        mp4video = convertor.convertVideo("youtubevideo.ogg", "mp4");
        mp4video.save();

適用性

  • 當你需要一個簡單但是功能有限的複雜子系統接口時
    通常,子系統隨着時間的推移變得越來越複雜。即使使用了設計模式也難避免創建更多的類。子系統可能變的更加靈活並且在不同的環境中複用性更高,但是它的樣板代碼數量也會隨之增長。門面模式嘗試通過提供訪問子系統的一部分來適應更多客戶端的需要。

  • 當你想把一個子系統構建成層
    創建門面來定義每個層子系統的連接點。如果多子系統之間相互依賴,你可以通過要求子系統只能通過門面交互來限制耦合。

如何實現

  1. 檢查是否可以使用簡化的接口和一個複雜的子系統交互。
    如果接口使客戶端沒有子系統的依賴,你就在正確的軌道上。

  2. 創建一個門面類並在接口中描述它。它必須能夠引導客戶端調用適當的子系統對象。門面應該關心子系統正確的初始化。通常,這些代碼在門面的構造方法中,懶實例化往往比較有用。

  3. 如果客戶端僅和門面協作,你將得到巨大的收益。在這種情況下,客戶端不需要關心子系統代碼的變化。比如,當一個庫的代碼更新世,你只需要修改門面。

  4. 如果這個門面變的太大,請考慮抽離出一個新的門面。

優點

  • 分離客戶端和子系統組件。

  • 客戶端代碼和子系統最小耦合。

缺點

  • 門面可能造成god object,它和所有應用類耦合。

和其他模式的關係

  • Facade重新定義了一個接口,而Adapter重用了一個老接口。記住,Adapter使兩個已存在接口協作,反對完全重新定義一個接口。

  • Abstract Factory可以用來替代Facade來隱藏平臺特定的類。

  • Flyweight展示如何製造更多小對象,而Facade展示如何使用一個對象代表整個子系統。

  • Meditor在抽象已存在類的功能上和Facade很像。Mediator抽象/集中兩個隨意交互的協作對象。它常規的做法是“add values”,並且協作對象間相互知道被引用。相比之下,Facade爲子系統定義了一個簡單的接口,它並不添加新功能,並且子系統類不知道它的存在。

  • Facade可以被改造成Singleton,因爲大多情況下單例門面對象就夠了。

  • Facade在緩衝一個複雜實體和初始化這點上和Proxy很像。不像Facade,Proxy模式和他服務的對象擁有相同的接口,使得它們是通用的。

Java中模式的使用

用例:在用Java寫的app中,門面模式很常見。它特別用來處理和複雜類庫和API協作的情景。

鑑定:Facade可以在具有簡單接口的類中被識別,但是它將大部分工作委託給其他類。通常,門面管理它們使用對象的生命週期。

參考

翻譯整理自:https://refactoring.guru/design-patterns/facade

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章