日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
Dubbo中用到了哪些設(shè)計(jì)模式?

介紹

策略模式

這個(gè)毫無(wú)爭(zhēng)議,Dubbo是基于SPI來(lái)擴(kuò)展的,SPI就是典型的策略模式。

專(zhuān)注于為中小企業(yè)提供網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)烏當(dāng)免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了近1000家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

Dubbo中可替換的組件太多了,例如負(fù)載均衡策略

實(shí)現(xiàn)類(lèi) 解釋
RandomLoadBalance隨機(jī)策略(默認(rèn))
RoundRobinLoadBalance輪詢策略
LeastActiveLoadBalance最少活躍調(diào)用數(shù)
ConsistentHashLoadBalance一致性hash策略

工廠模式

「簡(jiǎn)單工廠模式」:提供一個(gè)方法,返回創(chuàng)建好的對(duì)象

 
 
 
 
  1. public class VideoFactory { 
  2.  
  3.     public static Video getVideo(String type) { 
  4.         if ("java".equalsIgnoreCase(type)) { 
  5.             return new JavaVideo(); 
  6.         } else if ("python".equalsIgnoreCase(type)) { 
  7.             return new PythonVideo(); 
  8.         } 
  9.         return null; 
  10.     } 

「工廠方法模式」:當(dāng)工廠想提供更多產(chǎn)品時(shí),還得對(duì)創(chuàng)建過(guò)程進(jìn)行修改,因此抽象出一個(gè)工廠類(lèi),當(dāng)增加一種產(chǎn)品,就增加一個(gè)工廠類(lèi)(繼承抽象工廠類(lèi)或?qū)崿F(xiàn)接口)。這樣就實(shí)現(xiàn)了對(duì)擴(kuò)展開(kāi)發(fā),對(duì)修改關(guān)閉

 
 
 
 
  1. public abstract class VideoFactory { 
  2.  
  3.     public abstract Video getVideo(); 
  4. public class JavaVideoFactory extends VideoFactory { 
  5.     public Video getVideo() { 
  6.         return new JavaVideo(); 
  7.     } 
  8. public class Test { 
  9.  
  10.     public static void main(String[] args) { 
  11.         VideoFactory videoFactory = new JavaVideoFactory(); 
  12.         Video video = videoFactory.getVideo(); 
  13.         // 學(xué)習(xí)Java視頻 
  14.         video.study(); 
  15.     } 

「抽象工廠模式」:當(dāng)生產(chǎn)的產(chǎn)品較多時(shí),如果我們用工廠方法模式會(huì)造成類(lèi)爆照,此時(shí)我們就可以把相關(guān)的產(chǎn)品生產(chǎn)放到一個(gè)工廠類(lèi)中

 
 
 
 
  1. public abstract class CourseFactory { 
  2.  
  3.     public abstract Video getVideo(); 
  4.     public abstract Article getArticle(); 
  5. public class JavaCourseFactory extends CourseFactory { 
  6.     public Video getVideo() { 
  7.         return new JavaVideo(); 
  8.     } 
  9.  
  10.     public Article getArticle() { 
  11.         return new JavaArticle(); 
  12.     } 

因?yàn)镴avaVideo和JavaArticle都是Java相關(guān)的資料,所以可以用一個(gè)工廠類(lèi)來(lái)生產(chǎn)。如果用工廠方法模式來(lái)設(shè)計(jì)的話,JavaVideo和JavaArticle都會(huì)有一個(gè)對(duì)應(yīng)的工廠類(lèi)

簡(jiǎn)單工廠模式

 
 
 
 
  1. public class LoggerFactory { 
  2.  
  3.     public static Logger getLogger(Class key) { 
  4.         return LOGGERS.computeIfAbsent(key.getName(), name -> new FailsafeLogger(LOGGER_ADAPTER.getLogger(name))); 
  5.     } 

工廠方法模式

Dubbo可以對(duì)結(jié)果進(jìn)行緩存,緩存的策略有很多種,一種策略對(duì)應(yīng)一個(gè)緩存工廠類(lèi)

 
 
 
 
  1. @SPI("lru") 
  2. public interface CacheFactory { 
  3.  
  4.     @Adaptive("cache") 
  5.     Cache getCache(URL url, Invocation invocation); 
  6.  

抽象工廠模式

在RPC框架中,客戶端發(fā)送請(qǐng)求和服務(wù)端執(zhí)行請(qǐng)求的過(guò)程都是由代理類(lèi)來(lái)完成的。客戶端的代理對(duì)象叫做Client Stub,服務(wù)端的代理對(duì)象叫做Server Stub。

 
 
 
 
  1. @SPI("javassist") 
  2. public interface ProxyFactory { 
  3.  
  4.     // 針對(duì)consumer端,創(chuàng)建出代理對(duì)象 
  5.     @Adaptive({Constants.PROXY_KEY}) 
  6.      T getProxy(Invoker invoker) throws RpcException; 
  7.  
  8.     // 針對(duì)consumer端,創(chuàng)建出代理對(duì)象 
  9.     @Adaptive({Constants.PROXY_KEY}) 
  10.      T getProxy(Invoker invoker, boolean generic) throws RpcException; 
  11.  
  12.     // 針對(duì)provider端,將服務(wù)對(duì)象包裝成一個(gè)Invoker對(duì)象 
  13.     @Adaptive({Constants.PROXY_KEY}) 
  14.      Invoker getInvoker(T proxy, Class type, URL url) throws RpcException; 
  15.  

單例模式

服務(wù)導(dǎo)出的過(guò)程中,為了防止開(kāi)啟多個(gè)NettyServer,用了單例模式

 
 
 
 
  1. private void openServer(URL url) { 
  2.     // find server. 
  3.     String key = url.getAddress(); 
  4.     //client can export a service which's only for server to invoke 
  5.     boolean isServer = url.getParameter(Constants.IS_SERVER_KEY, true); 
  6.     if (isServer) { 
  7.         ExchangeServer server = serverMap.get(key); 
  8.         if (server == null) { 
  9.             synchronized (this) { 
  10.                 server = serverMap.get(key); 
  11.                 if (server == null) { 
  12.                     // 創(chuàng)建服務(wù)器實(shí)例 
  13.                     serverMap.put(key, createServer(url)); 
  14.                 } 
  15.             } 
  16.         } else { 
  17.             // server supports reset, use together with override 
  18.             server.reset(url); 
  19.         } 
  20.     } 

裝飾者模式

Dubbo中網(wǎng)絡(luò)傳輸層用到了Netty,當(dāng)我們用Netty開(kāi)發(fā)時(shí),一般都是寫(xiě)多個(gè)ChannelHandler,然后將這些ChannelHandler添加到ChannelPipeline上,就是典型的責(zé)任鏈模式

但是Dubbo考慮到有可能替換網(wǎng)絡(luò)框架組件,所以整個(gè)請(qǐng)求發(fā)送和請(qǐng)求接收的過(guò)程全部用的都是裝飾者模式。即只有NettyServerHandler實(shí)現(xiàn)的接口是Netty中的ChannelHandler,剩下的接口實(shí)現(xiàn)的是Dubbo中的ChannelHandler

如下是服務(wù)端消息接收會(huì)經(jīng)過(guò)的ChannelHandler

代理模式

前面說(shuō)過(guò)了哈,Client Stub和Server Stub都是代理對(duì)象

適配器模式

Dubbo可以支持多個(gè)日志框架,每個(gè)日志框架的實(shí)現(xiàn)都有對(duì)應(yīng)的Adapter類(lèi),為什么要搞Adapter類(lèi)呢,因?yàn)镈ubbo中日志接口Logger用的是自己的,而實(shí)現(xiàn)類(lèi)是引入的。但這些日志實(shí)現(xiàn)類(lèi)的等級(jí)和Dubbo中定義的日志等級(jí)并不完全一致,例如JdkLogger中并沒(méi)有trace和debug這個(gè)等級(jí),所以要用Adapter類(lèi)把Logger中的等級(jí)對(duì)應(yīng)到實(shí)現(xiàn)類(lèi)中的合適等級(jí)

 
 
 
 
  1. public interface Logger 
  2.  
  3.     // 省略部分代碼 
  4.      
  5.     void trace(String msg); 
  6.  
  7.     void debug(String msg); 
  8.  
  9.     void info(String msg); 
  10.  
  11.     void warn(String msg); 
  12.  

Dubbo接口中定義的日志等級(jí) JdkLogger對(duì)應(yīng)的日志等級(jí) Slf4jLogger對(duì)應(yīng)的日志等級(jí)
tracefinertrace
debugfinerdebug
infoinfoinfo

觀察者模式

在Dubbo中提供了各種注冊(cè)中心的實(shí)現(xiàn),類(lèi)圖如下。AbstractRegistry對(duì)注冊(cè)中心的內(nèi)容進(jìn)行了緩存,這樣能保證當(dāng)注冊(cè)中心不可用的時(shí)候,還能正常提供服務(wù)

「既然對(duì)注冊(cè)中心的內(nèi)容進(jìn)行了緩存,那么注冊(cè)中心的內(nèi)容發(fā)生改變的時(shí)候,怎么通知客戶端呢?」

例如客戶端從注冊(cè)中心獲取到服務(wù)端的地址,并緩存到本地,如果服務(wù)端宕機(jī)了,本地緩存怎么清除呢?此時(shí)就得需要對(duì)有可能變動(dòng)的節(jié)點(diǎn)進(jìn)行訂閱。當(dāng)節(jié)點(diǎn)發(fā)生變化的時(shí)候,就能收到通知,這樣就能更新本地緩存。

NotifyListener就是接收節(jié)點(diǎn)變動(dòng)的接口,各種注冊(cè)中心的節(jié)點(diǎn)發(fā)生變化都會(huì)主動(dòng)回調(diào)這個(gè)接口

 
 
 
 
  1. public interface RegistryService { 
  2.  
  3.     // 注冊(cè) 
  4.     void register(URL url); 
  5.  
  6.     // 注銷(xiāo) 
  7.     void unregister(URL url); 
  8.  
  9.     // 訂閱,訂閱的數(shù)據(jù)發(fā)生變化,會(huì)主動(dòng)通知NotifyListener#notify方法 
  10.     void subscribe(URL url, NotifyListener listener); 
  11.  
  12.     // 退訂 
  13.     void unsubscribe(URL url, NotifyListener listener); 
  14.  
  15.     // 查找服務(wù)地址 
  16.     List lookup(URL url); 
  17.  

責(zé)任鏈模式

代理對(duì)象(Client Stub或者Server Stub)在執(zhí)行的過(guò)程中會(huì)執(zhí)行所有Filter的invoke方法,但是這個(gè)實(shí)現(xiàn)方法是對(duì)對(duì)象不斷進(jìn)行包裝,看起來(lái)非常像裝飾者模式,但是基于方法名和這個(gè)Filter的功能,我更覺(jué)得這個(gè)是責(zé)任鏈模式

 
 
 
 
  1. private static  Invoker buildInvokerChain(final Invoker invoker, String key, String group) { 
  2.     Invoker last = invoker; 
  3.     // 獲取自動(dòng)激活的擴(kuò)展類(lèi) 
  4.     List filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group); 
  5.     if (!filters.isEmpty()) { 
  6.         for (int i = filters.size() - 1; i >= 0; i--) { 
  7.             final Filter filter = filters.get(i); 
  8.             final Invoker next = last; 
  9.             last = new Invoker() { 
  10.  
  11.                 // 省略部分代碼 
  12.  
  13.                 @Override 
  14.                 public Result invoke(Invocation invocation) throws RpcException { 
  15.                     // filter 不斷的套在 Invoker 上,調(diào)用invoke方法的時(shí)候就會(huì)執(zhí)行filter的invoke方法 
  16.                     Result result = filter.invoke(next, invocation); 
  17.                     if (result instanceof AsyncRpcResult) { 
  18.                         AsyncRpcResult asyncResult = (AsyncRpcResult) result; 
  19.                         asyncResult.thenApplyWithContext(r -> filter.onResponse(r, invoker, invocation)); 
  20.                         return asyncResult; 
  21.                     } else { 
  22.                         return filter.onResponse(result, invoker, invocation); 
  23.                     } 
  24.                 } 
  25.  
  26.             }; 
  27.         } 
  28.     } 
  29.     return last; 

本文轉(zhuǎn)載自微信公眾號(hào)「Java識(shí)堂」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系Java識(shí)堂公眾號(hào)。


網(wǎng)站名稱(chēng):Dubbo中用到了哪些設(shè)計(jì)模式?
分享地址:http://m.5511xx.com/article/cdieedo.html