我們先來分析代理這個詞。
一、代理
代理是英文 Proxy 翻譯過來的。我們在生活中見到過的代理,大概最常見的就是朋友圈中賣面膜的同學了。
她們從廠家拿貨,然後在朋友圈中宣傳,然後賣給熟人。
按理說,顧客可以直接從廠家購買產品,但是現實生活中,很少有這樣的銷售模式。一般都是廠家委託給代理商進行銷售,顧客跟代理商打交道,而不直接與產品實際生產者進行關聯。
所以,代理就有一種中間人的味道。
接下來,我們說說軟件中的代理模式。
二、代理模式
代理模式是面向對象編程中比較常見的設計模式。
這是常見代理模式常見的 UML 示意圖。
需要注意的有下面幾點:
- 用戶只關心接口功能,而不在乎誰提供了功能。上圖中接口是 Subject。
- 接口真正實現者是上圖的 RealSubject,但是它不與用戶直接接觸,而是通過代理。
- 代理就是上圖中的 Proxy,由於它實現了 Subject 接口,所以它能夠直接與用戶接觸。
- 用戶調用 Proxy 的時候,Proxy 內部調用了 RealSubje
三、代理模式的實例程序
我們將創建一個 Image 接口和實現了 Image 接口的實體類。ProxyImage 是一個代理類,減少 RealImage 對象加載的內存佔用。
ProxyPatternDemo,我們的演示類使用 ProxyImage 來獲取要加載的 Image 對象,並按照需求進行顯示。
步驟 1
創建一個接口。
Image.java
public interface Image { void display(); }
步驟 2
創建實現接口的實體類。
RealImage.java
public class RealImage implements Image { private String fileName; public RealImage(String fileName){ this.fileName = fileName; loadFromDisk(fileName); } @Override public void display() { System.out.println("Displaying " + fileName); } private void loadFromDisk(String fileName){ System.out.println("Loading " + fileName); } }
ProxyImage.java
public class ProxyImage implements Image{ private RealImage realImage; private String fileName; public ProxyImage(String fileName){ this.fileName = fileName; } @Override public void display() { if(realImage == null){ realImage = new RealImage(fileName); } realImage.display(); } }
步驟 3
當被請求時,使用 ProxyImage 來獲取 RealImage 類的對象。
ProxyPatternDemo.java
public class ProxyPatternDemo { public static void main(String[] args) { Image proxyImage = new ProxyImage("test_10mb.jpg"); // 圖像將從磁盤加載 proxyImage.display(); System.out.println(""); // 圖像不需要從磁盤加載 proxyImage.display(); } }
步驟 4
執行程序,輸出結果:
Loading test_10mb.jpg Displaying test_10mb.jpg Displaying test_10mb.jpg
四、代理模式分析
代理模式中的角色:
-
Subject(主體)
Subject角色定義了使proxy和realsubject角色之間具有一致性的接口。這個接口提供了一個使用的好處,就是client不必卻分它使用的是代理對象還是真實對象。
對應實例中Printable角色 -
Proxy(代理人)
Proxy角色會盡量處理來自Client角色的請求。只有當自己不能處理的時候,就交給工作交給真實對象。代理對象只有在有必要時纔會生成真實的對象。
實例中對應的是PrinterProxy對象。 -
RealSubject(真實對象)
就是實際完成工作的對象,對應實例中的Printer對象。
代理模式的類圖:
- 用代理人來提升速度
關鍵就在於延遲初始化。
我們可以等到需要使用到真實對象的功能才初始化。這樣的好處就是可以提升性能。從我們的實例中可能看不出這個優勢,假設我們有一個大型系統,如果我們都在系統啓動的時候,把所有功能初始化,所有實例初始化,那麼顯然系統的啓動將會變得很慢。但如果我們採用代理模式,那麼就會在必須的時候,在初始化對象。這樣就加快了系統的啓動速度。 - 代理和委託
其實我們學習了那麼多設計模式,是不是感覺委託簡直無處不在。幾乎每個設計模式都會用到委託,代理模式也不意外,就是代理了對象委託了真實對象。
因爲委託可以是對象之間發生聯繫,互相調用。所以委託在很多設計模式中都存在。
參考文章 :
- https://www.jianshu.com/p/5ab7672b935f
- https://blog.csdn.net/briblue/article/details/73928350
- https://www.runoob.com/design-pattern/proxy-pattern.html