在有些情况下,一个客户不能或者不想直接访问另一个对象,这时需要找一个中介帮忙完成某项任务,这个中介就是代理对象。 定义与特点由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。 主要优点有:
主要缺点有:
结构与实现代理模式的结构比较简单,主要是通过定义一个继承抽象主题的代理来包含真实主题,从而实现对真实主题的访问。 模式的结构代理模式的主要角色如下:
其结构图如图所示: 模式的实现代理模式的实现代码如下: //访问类 class Program { static void Main(string[] args) { //代理模式 Proxy proxy=new Proxy(); proxy.Request(); Console.ReadKey(); } } //抽象主题 public interface ISubject { void Request(); } //真实主题 public class RealSubject :ISubject { public void Request() { Console.WriteLine("访问真实主题方法..."); } } //代理 public class Proxy : ISubject { private RealSubject realSubject; public void Request() { if (realSubject==null) { realSubject=new RealSubject(); } PreRequest(); realSubject.Request(); PostRequest(); } public void PreRequest() { Console.WriteLine("访问真实主题之前的预处理。"); } public void PostRequest() { Console.WriteLine("访问真实主题之后的后续处理。"); } } 程序运行的结果如下: 访问真实主题之前的预处理。 访问真实主题方法... 访问真实主题之后的后续处理。 应用场景前面分析了代理模式的结构与特点,现在来分析以下的应用场景:
扩展:动态代理模式在前面介绍的代理模式中,代理类中包含了对真实主题的引用,这种方式存在两个缺点:
采用动态代理模式可以解决以上问题(如 SpringAOP),C#中可以使用RealProxy实现动态代理,有两种方法: class Program { static void Main(string[] args) { Console.WriteLine("***\r\n Begin program - logging with decorator\r\n"); IRepository<Customer> customerRepository =RepositoryFactory.Create<Customer>(); var customer = new Customer() { Id = 1, Name = "Customer 1", Address = "Address 1" }; customerRepository.Add(customer); customerRepository.Update(customer); customerRepository.Delete(customer); Console.WriteLine("\r\nEnd program - logging with decorator\r\n***"); Console.ReadLine(); } } //客户类 public class Customer { public int Id { get; set; } public string Name { get; set; } public string Address { get; set; } } //存储库接口 public interface IRepository<T> { void Add(T entity); void Delete(T entity); void Update(T entity); IEnumerable<T> GetAll(); T GetById(int id); } //真实储存库 public class Repository<T> : IRepository<T> { public void Add(T entity) { Console.WriteLine("Adding {0}", entity); } public void Delete(T entity) { Console.WriteLine("Deleting {0}", entity); } public void Update(T entity) { Console.WriteLine("Updating {0}", entity); } public IEnumerable<T> GetAll() { Console.WriteLine("Getting entities"); return null; } public T GetById(int id) { Console.WriteLine("Getting entity {0}", id); return default(T); } } //动态代理 class DynamicProxy<T> : RealProxy { private readonly T _decorated; public DynamicProxy(T decorated) : base(typeof(T)) { _decorated = decorated; } private void Log(string msg, object arg = null) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(msg, arg); Console.ResetColor(); } public override IMessage Invoke(IMessage msg) { var methodCall = msg as IMethodCallMessage; var methodInfo = methodCall.MethodBase as MethodInfo; Log("In Dynamic Proxy - Before executing '{0}'",methodCall.MethodName); try { var result = methodInfo.Invoke(_decorated, methodCall.InArgs); Log("In Dynamic Proxy - After executing '{0}' ",methodCall.MethodName); return new ReturnMessage(result, null, 0,methodCall.LogicalCallContext, methodCall); } catch (Exception e) { Log(string.Format("In Dynamic Proxy- Exception {0} executing '{1}'", e),methodCall.MethodName); return new ReturnMessage(e, methodCall); } } } //存仓库过程,自动执行代理 public class RepositoryFactory { public static IRepository<T> Create<T>() { var repository = new Repository<T>(); var dynamicProxy = new DynamicProxy<IRepository<T>>(repository); return dynamicProxy.GetTransparentProxy() as IRepository<T>; } } 第二种:使用RealProxy、MarshalByRefObject,可以代理带out参数的方法,代码如下: //访问类 public class Program { static void Main(string[] args) { //动态代理模式 Proxy<ISubject> proxy = new Proxy<ISubject>(new RealSubject()); ISubject subject = (ISubject)proxy.GetTransparentProxy(); int arg = 0; subject.Request(out arg); Console.WriteLine(arg); Console.ReadKey(); } } //代理类 public class Proxy<T> : RealProxy where T: class { MarshalByRefObject myMarshalByRefObject; public Proxy(MarshalByRefObject realT) : base(typeof(T)) { myMarshalByRefObject = realT; } public override IMessage Invoke(IMessage myMessage) { IMethodCallMessage myCallMessage = (IMethodCallMessage)myMessage; Console.WriteLine("动态代理方法中:执行前"); IMethodReturnMessage myIMethodReturnMessage = RemotingServices.ExecuteMessage(myMarshalByRefObject, myCallMessage); Console.WriteLine("动态代理方法中:执行后"); return myIMethodReturnMessage; } } //抽象主题 public interface ISubject { void Request(out int arg); } //真实主题 public class RealSubject : MarshalByRefObject,ISubject { public void Request(out int arg) { arg = 1; Console.WriteLine("访问真实主题方法..."); } } 参考资料 |
|