代理模式提供了一箇中介控制對某個物件的訪問。現實生活中,我們可能會用支票在市場交易中用來代替現金,支票就是賬戶中資金的代理。
1、代理模式簡介
1.1>、定義
代理模式(Proxy)定義:代理模式為客戶端程式提供一種中間層以控制對這個物件的訪問。
1.2>、使用頻率
中高
2、代理模式結構
2.1>、結構圖
2.2>、參與者
代理模式參與者:
◊ Proxy
° 維持一個引用,使得代理可以訪問Subject。
° 提供一個與Subject的介面相同的介面,這樣代理就可以替代Subject。
° 控制對Subject的訪問,並可能負責對Subject的建立和刪除。
◊ Subject:定義ConcreteSubject與Proxy的共用介面,從而在任何使用ConcreteSubject的地方都可以使用Proxy。
◊ ConcreteSubject:定義Proxy所代表的Subject。
◊ Client:維持一個對Subject的引用
在代理模式中,由於Proxy與ConcreteSubject繼承同一介面,所以Client呼叫ConcreteSubject可以轉化為Client呼叫Proxy在呼叫ConcreteSubject,類Proxy為中間代理。
3、代理模式結構實現
Subject.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.ProxyPattern.Structural { public abstract class Subject { public abstract void Request(); } }
ConcreteSubject.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.ProxyPattern.Structural { public class ConcreteSubject : Subject { public override void Request() { Console.WriteLine("Called ConcreteSubject.Request()"); } } }
Proxy.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.ProxyPattern.Structural { public class Proxy : Subject { private ConcreteSubject _concreteSubject; public override void Request() { // Use 'lazy initialization' if (_concreteSubject == null) { _concreteSubject = new ConcreteSubject(); } _concreteSubject.Request(); } } }
Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using DesignPatterns.ProxyPattern.Structural; namespace DesignPatterns.ProxyPattern { class Program { static void Main(string[] args) { // Create proxy and request a service Proxy proxy = new Proxy(); proxy.Request(); } } }
執行輸出:
Called ConcreteSubject.Request()
請按任意鍵繼續. . .
4、代理模式實踐應用
IMath.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.ProxyPattern.Practical { /// <summary> /// The 'Subject interface /// </summary> public interface IMath { double Add(double x, double y); double Sub(double x, double y); double Mul(double x, double y); double Div(double x, double y); } }
Math.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.ProxyPattern.Practical { /// <summary> /// The 'ConcreteSubject' class /// </summary> public class Math : IMath { public double Add(double x, double y) { return x + y; } public double Sub(double x, double y) { return x - y; } public double Mul(double x, double y) { return x * y; } public double Div(double x, double y) { return x / y; } } }
MathProxy.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.ProxyPattern.Practical { public class MathProxy : IMath { private Math _math = new Math(); public double Add(double x, double y) { return _math.Add(x, y); } public double Sub(double x, double y) { return _math.Sub(x, y); } public double Mul(double x, double y) { return _math.Mul(x, y); } public double Div(double x, double y) { return _math.Div(x, y); } } }
Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using DesignPatterns.ProxyPattern.Practical; namespace DesignPatterns.ProxyPattern { class Program { static void Main(string[] args) { // Create math proxy MathProxy proxy = new MathProxy(); // Do the math Console.WriteLine("4 + 2 = " + proxy.Add(4, 2)); Console.WriteLine("4 - 2 = " + proxy.Sub(4, 2)); Console.WriteLine("4 * 2 = " + proxy.Mul(4, 2)); Console.WriteLine("4 / 2 = " + proxy.Div(4, 2)); } } }
執行輸出:
4 + 2 = 6 4 - 2 = 2 4 * 2 = 8 4 / 2 = 2 請按任意鍵繼續. . .
5、代理模式應用分析
代理模式適用範圍很廣,不同的代理適合於不同的情形。
◊ 遠端代理為一個物件在不同的地址空間提供區域性代表。
◊ 虛代理在需要建立開銷很大的物件時快取物件資訊。
◊ 保護代理控制對原始物件的訪問。保護代理用於物件應該有不同的訪問許可權的時候。
◊ 智慧指引取代了簡單指引,它在訪問物件時執行了一些附加操作。它的典型用途包括:對指向實際物件的引用計數,這樣當該物件沒有引用時,可以自動釋放。當第一次引用一個持久物件時,將它裝入記憶體。在訪問一個實際物件前,檢查是否已經鎖定了它,以確保其他物件不能改變它。
代理模式特點:
◊ 代理模式在訪問物件時引入一定程度的間接性,可以隱藏物件的位置。
◊ 代理模式可以對使用者隱藏一種稱之為copy-on-write的優化方式。當進行一個開銷很大的複製操作的時候,如果複製沒有被修改,則代理延遲這一複製過程,這一可以保證只有當這個物件被修改的時候才對它進行復制。
6、代理模式與裝飾模式比較分析
裝飾器模式關注於在一個物件上動態的新增方法,代理模式關注於控制對物件的訪問。
裝飾器模式中Decorator和ConcreteComponent都實現Component,代理模式中Proxy和ConcreteSubject都實現Subject。使用這兩種模式,都可以很容易地在具體物件的方法前面或者後面加上自定義的方法。
Proxy 可以對Client隱藏物件的具體資訊,在使用代理模式時,常在Proxy中建立一個物件的例項。Proxy與ConcreteSubject之間的關係在編譯時就能確定。
在使用裝飾模式時,常是將ConcreteComponent物件作為一個引數傳給ConcreteDecorator的構造器,Decorator在執行時遞迴的被構造。