最近在看阿里開源RPC框架Dubbo的源碼,順帶梳理了一下其中用到的設計模式。下面將逐個列舉其中的設計模式,并根據(jù)自己的理解分析這樣設計的原因和優(yōu)劣。
責任鏈模式
責任鏈模式在Dubbo中發(fā)揮的作用舉足輕重,就像是Dubbo框架的骨架。Dubbo的調(diào)用鏈組織是用責任鏈模式串連起來的。責任鏈中的每個節(jié)點實現(xiàn)Filter接口,然后由ProtocolFilterWrapper,將所有Filter串連起來。Dubbo的許多功能都是通過Filter擴展實現(xiàn)的,比如監(jiān)控、日志、緩存、安全、telnet以及RPC本身都是。如果把Dubbo比作一列火車,責任鏈就像是火車的各車廂,每個車廂的功能不同。如果需要加入新的功能,增加車廂就可以了,非常容易擴展。
觀察者模式
Dubbo中使用觀察者模式最典型的例子是RegistryService。消費者在初始化的時候回調(diào)用subscribe方法,注冊一個觀察者,如果觀察者引用的服務地址列表發(fā)生改變,就會通過NotifyListener通知消費者。此外,Dubbo的InvokerListener、ExporterListener?也實現(xiàn)了觀察者模式,只要實現(xiàn)該接口,并注冊,就可以接收到consumer端調(diào)用refer和provider端調(diào)用export的通知。Dubbo的注冊/訂閱模型和觀察者模式就是天生一對。
修飾器模式
Dubbo中還大量用到了修飾器模式。比如ProtocolFilterWrapper類是對Protocol類的修飾。在export和refer方法中,配合責任鏈模式,把Filter組裝成責任鏈,實現(xiàn)對Protocol功能的修飾。其他還有ProtocolListenerWrapper、?ListenerInvokerWrapper、InvokerWrapper等。個人感覺,修飾器模式是一把雙刃劍,一方面用它可以方便地擴展類的功能,而且對用戶無感,但另一方面,過多地使用修飾器模式不利于理解,因為一個類可能經(jīng)過層層修飾,最終的行為已經(jīng)和原始行為偏離較大。
工廠方法模式
CacheFactory的實現(xiàn)采用的是工廠方法模式。CacheFactory接口定義getCache方法,然后定義一個AbstractCacheFactory抽象類實現(xiàn)CacheFactory,并將實際創(chuàng)建cache的createCache方法分離出來,并設置為抽象方法。這樣具體cache的創(chuàng)建工作就留給具體的子類去完成。
抽象工廠模式
ProxyFactory及其子類是Dubbo中使用抽象工廠模式的典型例子。ProxyFactory提供兩個方法,分別用來生產(chǎn)Proxy和Invoker(這兩個方法簽名看起來有些矛盾,因為getProxy方法需要傳入一個Invoker對象,而getInvoker方法需要傳入一個Proxy對象,看起來會形成循環(huán)依賴,但其實兩個方式使用的場景不一樣)。AbstractProxyFactory實現(xiàn)了ProxyFactory接口,作為具體實現(xiàn)類的抽象父類。然后定義了JdkProxyFactory和JavassistProxyFactory兩個具體類,分別用來生產(chǎn)基于jdk代理機制和基于javassist代理機制的Proxy和Invoker。
適配器模式
為了讓用戶根據(jù)自己的需求選擇日志組件,Dubbo自定義了自己的Logger接口,并為常見的日志組件(包括jcl, jdk, log4j, slf4j)提供相應的適配器。并且利用簡單工廠模式提供一個LoggerFactory,客戶可以創(chuàng)建抽象的Dubbo自定義Logger,而無需關心實際使用的日志組件類型。在LoggerFactory初始化時,客戶通過設置系統(tǒng)變量的方式選擇自己所用的日志組件,這樣提供了很大的靈活性。
代理模式
Dubbo consumer使用Proxy類創(chuàng)建遠程服務的本地代理,本地代理實現(xiàn)和遠程服務一樣的接口,并且屏蔽了網(wǎng)絡通信的細節(jié),使得用戶在使用本地代理的時候,感覺和使用本地服務一樣。