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了
}
}代理