自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Nacos竟然是這樣使用代理模式的?

開發(fā) 前端
隨著對Nacos源碼的深入閱讀,感覺越來越有意思了,大量的設計模式和基礎知識點都在其中被運用。不論你是否閱讀源碼,都值得借鑒一下Nacos的運用案例。

[[413647]]

本文轉載自微信公眾號「程序新視界」,作者丑胖俠二師兄 。轉載本文請聯系程序新視界公眾號。

學習不用那么功利,二師兄帶你從更高維度輕松閱讀源碼~

隨著對Nacos源碼的深入閱讀,感覺越來越有意思了,大量的設計模式和基礎知識點都在其中被運用。不論你是否閱讀源碼,都值得借鑒一下Nacos的運用案例。

今天這篇文章,給大家介紹一下Nacos Client中對代理模式的運用。閱讀這篇文章,你可以不懂Nacos源碼,但能夠學到代理模式的運用;如果你準備閱讀Nacos源碼,不僅可以學到代理模式的案例,還可以更加深刻的感知到Nacos中的設計思想。

代理模式簡介

通俗的來講,代理模式就是讓別人(代理)幫忙做你并不關心的事,作用就相當于日常生活中的中介。

比如,日常生活中,你想買輛車,你可以直接去自己挑選、質檢等,但這個過程會耗費你大量的時間和精力。那么,此時你就可以找一個代理,來幫忙實現挑選、質檢的事情。

對于軟件設計來說,代理模式的定義為:代理模式給某一個對象提供一個代理對象,并由代理對象控制對原對象的引用。通俗的來講代理模式就是我們生活中常見的中介。

代理模式的結構

在不使用代理模式時,我們大概是這樣使用一個接口:圖片

客戶端在使用CarService接口時需要創(chuàng)建CarServiceImpl類的實例,然后進行業(yè)務邏輯處理。

但在某些場景下,一個客戶類不想或者不能直接引用一個委托對象(CarServiceImpl),此時代理類對象可以在客戶類和委托對象之間起到中介的作用,并提供相同的功能。

如果提供相同的功能,那么代理類和委托類就需要實現相同的接口。此時,上圖就演變成了代理模式:

代理模式

在代理模式的圖中,對比普通的直接使用,新增了代理類,并且代理類持有了委托類(真實對象)的引用。代理類本身并不真正實現服務,而是通過調用委托類的相關方法,來提供特定的服務,所以要持有真實類的引用。

代理類可以在業(yè)務功能執(zhí)行的前后加入一些公共的服務,比如負責為委托類預處理消息、過濾消息、把消息轉發(fā)給委托類,以及事后對返回結果的處理等。

代理模式中的角色:

  • 抽象主題類(Subject):聲明了目標對象和代理對象的共同接口,在任何可以使用目標對象的地方都可以使用代理對象。
  • 具體主題類(RealSubject):也稱為委托角色或者被代理角色。定義了代理對象所代表的目標對象。
  • 代理類(Proxy):也叫委托類、代理類。代理對象內部含有目標對象的引用,從而可以在任何時候操作目標對象;代理對象提供一個與目標對象相同的接口,以便可以在任何時候替代目標對象。代理對象通常在客戶端調用傳遞給目標對象之前或之后,執(zhí)行某個操作,而不是單純地將調用傳遞給目標對象。

代理模式實現

以上面的結構圖為例,來看看代理模式的代碼實現。

定義抽象主題類(CarService)、具體主題類(CarServiceImpl)、代理類(CarServiceProxy):

  1. // 抽象主題類 
  2. public interface CarService { 
  3.     // 選車 
  4.     Car chooseCar(); 
  5.     // 質量檢查 
  6.     boolean qualityCheck(); 
  7.  
  8. // 具體主題類 
  9. public class CarServiceImpl implements CarService { 
  10.     @Override 
  11.     public Car chooseCar() { 
  12.         System.out.println("真實操作:選車"); 
  13.         return new Car(); 
  14.     } 
  15.  
  16.     @Override 
  17.     public boolean qualityCheck() { 
  18.         System.out.println("真實操作:質量檢測"); 
  19.         return true
  20.     } 
  21.  
  22. // 代理類 
  23. public class CarServiceProxy implements CarService { 
  24.  
  25.     private CarServiceImpl real
  26.  
  27.     public CarServiceProxy() { 
  28.         real = new CarServiceImpl(); 
  29.     } 
  30.  
  31.     @Override 
  32.     public Car chooseCar() { 
  33.         System.out.println("代理類CarServiceProxy選車:先添加一些日志"); 
  34.         return real.chooseCar(); 
  35.     } 
  36.  
  37.     @Override 
  38.     public boolean qualityCheck() { 
  39.         System.out.println("代理類CarServiceProxy質量檢測:先添加一些日志"); 
  40.         return real.qualityCheck(); 
  41.     } 

對應的客戶端測試類:

  1. public class Client { 
  2.  
  3.     public static void main(String[] args) { 
  4.  
  5.         CarService carService = new CarServiceProxy(); 
  6.         carService.chooseCar(); 
  7.         carService.qualityCheck(); 
  8.     } 

直接使用代理類,就可以完成預期的工作。

執(zhí)行程序,打印日志如下:

  • 代理類CarServiceProxy選車:先添加一些日志
  • 真實操作:選車
  • 代理類CarServiceProxy質量檢測:先添加一些日志
  • 真實操作:質量檢測

可以看出,在真實的操作之前,可以通過代理類添加一些其他的操作。

Nacos的代理模式實踐

上面了解了代理模式的基本知識以及實例,下面就來看看Nacos中是如何實現代理模式的。

Nacos Client與注冊中心進行通信采用了兩種通信協議:HTTP協議和gRPC協議。這兩個協議實現了共同的抽象主題類NamingClientProxy,具體主題類有NamingHttpClientProxy和NamingGrpcClientProxy,分別對應Http協議和gRPC協議實現。

此時,Nacos考慮到要支持通過配置來靈活選擇具體的通信協議,而這個功能呢又沒辦法讓這兩個具體的主題類來實現,因此就產生了一個代理類NamingClientProxyDelegate來完成一些預先的處理和判斷。

整個代理模式的使用類圖如下:

代理模式

通過上圖可以發(fā)現,Nacos的代理模式使用與標準的代理模式還有一些區(qū)別。

首先,NamingClientProxyDelegate同時代理了具體主題類,這可能考慮的是方便通信協議的配置切換。同時,在代理類中還處理了一些事件監(jiān)聽等額外功能。

其次,說話Nacos這塊的命名并不友好,比如抽象主題直接以Proxy為后綴,容易讓人混淆。這就導致與代理模式中的代理類命名沖突,于是將代理類的后綴替換為了Delegate。

上圖中的客戶類便是NacosNamingService,在其中實現了代理類的初始化操作,具體代碼實現如下:

  1. public class NacosNamingService implements NamingService { 
  2.     // ... 
  3.     private NamingClientProxy clientProxy; 
  4.    
  5.     private void init(Properties properties) throws NacosException { 
  6.         // ... 
  7.         this.clientProxy = new NamingClientProxyDelegate(this.namespace, serviceInfoHolder, properties, changeNotifier); 
  8.     } 
  9.      
  10.     @Override 
  11.     public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException { 
  12.         NamingUtils.checkInstanceIsLegal(instance); 
  13.         clientProxy.registerService(serviceName, groupName, instance); 
  14.     } 
  15.     // ... 
  16. }   

抽象主題類NamingClientProxy為接口,部分代碼如下:

  1. public interface NamingClientProxy extends Closeable { 
  2.      
  3.     void registerService(String serviceName, String groupName, Instance instance) throws NacosException; 
  4.   
  5.     void deregisterService(String serviceName, String groupName, Instance instance) throws NacosException; 
  6.     
  7.    // ... 

代理類NamingClientProxyDelegate部分實現如下:

  1. public class NamingClientProxyDelegate implements NamingClientProxy { 
  2.     // ... 
  3.     private final NamingHttpClientProxy httpClientProxy; 
  4.      
  5.     private final NamingGrpcClientProxy grpcClientProxy; 
  6.      
  7.     public NamingClientProxyDelegate(String namespace, ServiceInfoHolder serviceInfoHolder, Properties properties, 
  8.             InstancesChangeNotifier changeNotifier) throws NacosException { 
  9.          // ...        
  10.         this.httpClientProxy = new NamingHttpClientProxy(namespace, securityProxy, serverListManager, properties, 
  11.                 serviceInfoHolder); 
  12.         this.grpcClientProxy = new NamingGrpcClientProxy(namespace, securityProxy, serverListManager, properties, 
  13.                 serviceInfoHolder); 
  14.     } 
  15.   // ... 

可以看出,代理類實現了NamingClientProxy接口,同時持有了NamingHttpClientProxy和NamingGrpcClientProxy的對象引用,并且對它們進行了初始化操作。

關于NamingHttpClientProxy和NamingGrpcClientProxy的代碼我們就不再展示,它們首先繼承了AbstractNamingClientProxy抽象類,該抽象類實現NamingClientProxy接口。

從整體上來說,Nacos中對代理模式的運用還是比較靈的,結合場景一個代理類代理了兩個具體實現類,但同時在命名方面的問題,還有待商榷。

代理模式和裝飾器模式的區(qū)別

在學習使用代理模式時,經常會有朋友與裝飾器模式相混淆。這里就簡單聊一下它們直接的區(qū)別。

裝飾器模式中,裝飾者(decorator)和被裝飾者(decoratee)都實現同一個接口。代理模式中,代理類(proxy class)和真實處理的類(real class)都實現同一個接口。而且兩者都對類的方法進行擴展,看起來邊界的確比較模糊。

但還是有一些區(qū)別點的:

  • 裝飾器模式強調的是增強自身,比如增加之后可提供更多的屬性和方法;代理模式強調要讓別人幫你去做一些本身與你業(yè)務沒有太多關系的職責(記錄日志、設置緩存)。代理模式是為了實現對象的控制,因為被代理的對象往往難以直接獲得或者是其內部不想暴露出來。
  • 裝飾模式是以對客戶端透明的方式擴展對象的功能,是繼承方案的一個替代方案;代理模式則是給一個對象提供一個代理對象,并由代理對象來控制對原有對象的引用;
  • 裝飾模式是為裝飾的對象增強功能;而代理模式對代理的對象施加控制,但不對對象本身的功能進行增強;

小結

 

代理模式在日常業(yè)務代碼中還是比較少見的,本文我們重點介紹了靜態(tài)代理模式及在Nacos中的運用。關于動態(tài)代理,在Spring的框架中可以看到很多實例,有機會我們再進行講解。而Nacos中對代理模式的運用算是比較靈活,同時也并不是那么完美。這或許也提供了我們對代理模式認知的另外一個視角。

 

責任編輯:武曉燕 來源: 程序新視界
相關推薦

2020-09-29 06:45:49

JDK

2020-12-15 08:05:40

路由器服務器網絡層

2021-08-28 10:15:26

項目結構Flask

2019-12-24 11:00:51

NVMeSSDSATA

2018-05-02 09:38:02

程序員代碼互聯網

2019-08-19 09:21:36

程序員Bug代碼

2018-06-23 13:49:56

蘋果谷歌手機

2024-08-05 01:28:26

2015-06-18 11:04:58

2024-09-27 11:38:49

2023-03-13 08:09:03

Protobuffeature分割

2018-07-06 00:09:47

2022-11-15 07:35:50

Spring事件觀察者模式

2021-10-18 13:42:52

加密貨幣金融工具

2016-03-04 14:14:02

電話免費越洋

2020-10-20 17:18:00

戴爾

2022-07-07 19:44:22

Python 3.1

2022-01-16 07:02:07

物聯網平臺物聯網IOT

2023-04-06 09:44:00

ChatGPT行業(yè)質量
點贊
收藏

51CTO技術棧公眾號