1、直接與間接
1)從們對於複雜的軟件系統經常有一種處理方法,即增長一層間接層,從而對系統得到一種更爲靈活、知足特定需求的解決方案。
A 直接:A對象直接使用B對象。
B 間接:C對象先使用B對象,A對象再去使用C對象,這樣A對象間接使用了B對象。
2、動機(Motivation)
1)在面向對象系統中,有些對象因爲某種緣由(好比對象建立的開銷很大,或者某些操做須要安全控制,或者須要進程外的訪問等),直接訪問會給使用者、或者系統結構帶來不少麻煩。
2)如何在不失去透明操做對象的同時來管理/控制這些對象特有的複雜性?增長一層間接層是軟件開發中常見的解決方式。
3、意圖(Intent)
爲其餘對象提供一種代理以控制對這個對象的訪問。
——《設計模式》GoF
4、實例:WebServices的分佈式開發
using System;設計模式
//Version 1.0
//這是一個運行在網絡WebServices上的對象
public class Employee
{
public void GetSalary()
{
//......
}
public void Report()
{
//......
}
public void ApplyVacation()
{
//......
}
}安全
public class HrSystem
{
public void Process()
{
//與WebServices位於同一進程空間
Employee employee = new Employee();
employee.Report();
//......
employee.ApplyVacation();
//......
}
}網絡
//Version 2.0
//運行在Internet上
public interface IEmployee
{
public void GetSalary();
public void Report();
public void ApplyVacation();
}架構
//運行在Internet遠端的一臺機器上
public class Employee : IEmployee
{
public void GetSalary()
{
//......
}
public void Report()
{
//......
}
public void ApplyVacation()
{
//......
}
}分佈式
//代理類:封裝掉SOAP協議相關的內容,讓客戶看不到這些
//運行在本地機器上:屏弊與WebServices通信的細節
public class EmployeeProxy : IEmployee
{
public EmployeeProxy()
{
//對對象建立的一種SOAP封裝
}
public void GetSalary()
{
//對對象訪問的一種SOAP封裝
//發送SOAP數據
//若是有返回值,接受返回值SOAP,解包,返回原生(raw)的C#數據
}
public void Report()
{
//一樣的方法實現
}
public void ApplyVacation()
{
//一樣的方法實現
}
}ui
public class HrSystem
{
public void Process()
{
IEmployee employee = new EmployeeProxy();
employee.Report();
//......
employee.ApplyVacation();
//......
}
}設計
5、Proxy模式的幾個要點
1)「增長一層間接層」是軟件系統中對許多複雜問題的一種常看法決方法。在面向對象系統中,直接使用某些對象會帶來不少問題,做爲間接層的proxy對象是解決這一問題的經常使用手段。
2)具體proxy設計模式的實現方法、實現粒度都相差很大,有些可能對單個對象作細粒度的控制,如copy-on-write技術,有些可能對組件模塊提供抽象代理層,在架構層對對象作proxy。
3)Proxy並不必定要求保持接口的一致性,只要可以實現間接控制,有時候損及一些透明性是能夠接受的。
6、Copy-on-write技術(這個技術是一個Proxy模式的應用)
public class App
{
public static void Main()
{
/*
string s1 = "Hello";
string s2 = "Hello";
//實際上s1和s2的值是相同的,它們指向相同的內存空間
string s3 = s1.ToUpper();
//s1 = s1.ToUpper();
//將s1轉換爲大小後,會在內存開闢一個空間,讓s3或s1指向它
*/
StringBuilder sb1 = new StringBuilder("Hello");
StringBuilder sb2 = new StringBuilder("Hello");
StringBuilder sb3 = new StringBuilder("Hello");
//sb1,sb2,sb3指向同一個內存空間
sb1.Replace('l', 'q');
//sb1不指向先前的內存空間了,它指向另外一個空間,sb1=Heqqo了
}
}代理