在有些情況下,一個客戶不能或者不想直接訪問另一個對象,這時需要找一個中介幫忙完成某項任務(wù),這個中介就是代理對象。 定義與特點由于某些原因需要給某對象提供一個代理以控制對該對象的訪問。這時,訪問對象不適合或者不能直接引用目標(biāo)對象,代理對象作為訪問對象和目標(biāo)對象之間的中介。 主要優(yōu)點有:
主要缺點有:
結(jié)構(gòu)與實現(xiàn)代理模式的結(jié)構(gòu)比較簡單,主要是通過定義一個繼承抽象主題的代理來包含真實主題,從而實現(xiàn)對真實主題的訪問。 模式的結(jié)構(gòu)代理模式的主要角色如下:
其結(jié)構(gòu)圖如圖所示: 模式的實現(xiàn)代理模式的實現(xiàn)代碼如下: //訪問類 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("訪問真實主題之前的預(yù)處理。"); } public void PostRequest() { Console.WriteLine("訪問真實主題之后的后續(xù)處理。"); } } 程序運(yùn)行的結(jié)果如下: 訪問真實主題之前的預(yù)處理。 訪問真實主題方法... 訪問真實主題之后的后續(xù)處理。 應(yīng)用場景前面分析了代理模式的結(jié)構(gòu)與特點,現(xiàn)在來分析以下的應(yīng)用場景:
擴(kuò)展:動態(tài)代理模式在前面介紹的代理模式中,代理類中包含了對真實主題的引用,這種方式存在兩個缺點:
采用動態(tài)代理模式可以解決以上問題(如 SpringAOP),C#中可以使用RealProxy實現(xiàn)動態(tài)代理,有兩種方法: 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); } } //動態(tài)代理 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); } } } //存?zhèn)}庫過程,自動執(zhí)行代理 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參數(shù)的方法,代碼如下: //訪問類 public class Program { static void Main(string[] args) { //動態(tài)代理模式 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("動態(tài)代理方法中:執(zhí)行前"); IMethodReturnMessage myIMethodReturnMessage = RemotingServices.ExecuteMessage(myMarshalByRefObject, myCallMessage); Console.WriteLine("動態(tài)代理方法中:執(zhí)行后"); 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("訪問真實主題方法..."); } } 參考資料C#中動態(tài)代理與泛型函數(shù)——CSDN |
|