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