代理在实际中应用场景主要为,在对一个已有的类的方法,进行先后记录一些操做。如当一个程序的方法运行时先后,添加一些日志记录或时间记录,以测量该方法运行所耗的时间。代理的实现分静态代理和动态代理,静态代理主要可经过继承与聚合进行实现。其中继承的实现,主要是在对须要添加代理的类进行扩展,而后按各类需求进行扩展,但此种方式的缺点是,若是同时须要两个代理功能,如先记录时间,而后记录日志,则可先让时间记录继承业务类,而后日志记录继承时间记录。但若是还须要先日志后记录时间,则又得再次写一套继承。如此,会致使类无快速增长。聚合的实现,则只须要将所实现同一接口的业务类对象进行前后传递便可。如下一步步在此,仅以简单的例子,一步步实现代理的实现原理。测试
1.基本的业务。假设有一个接口Runnable,如今让一个Car去实现它this
namespace FD.Pattern.ConsoleApplicationProxy { // CreatedOn: 2016-04-12 // CreatedBy: Jackie Lee /// <summary> /// 移动的接口 /// </summary> interface Runnable { void Run(); } } namespace FD.Pattern.ConsoleApplicationProxy { // CreatedOn: 2016-04-12 // CreatedBy: Jackie Lee /// <summary> /// 汽车 /// </summary> public class Car : Runnable { public void Run() { Console.WriteLine("The car is running..."); Thread.Sleep(500); } } }
为了后面能测试运行时间,在Car的实现中休息500毫秒。spa
2.新增要求。如今要求在不改变Car的状况下,记录下Car的Run运行时间,Car的Run状况信息进行日志记录。如下使用聚合方式实现简单的静态代理pwa
namespace FD.Pattern.ConsoleApplicationProxy { // CreatedOn: 2016-04-12 // CreatedBy: Jackie Lee /// <summary> /// 汽车移动日期代理 /// </summary> public class CarRunDateProxy : Runnable { private Car car; public CarRunDateProxy(Car car) { this.car = car; } public void Run() { Stopwatch watch = Stopwatch.StartNew(); car.Run(); Console.WriteLine("Car Move {0} ms", watch.ElapsedMilliseconds); } } } namespace FD.Pattern.ConsoleApplicationProxy { // CreatedOn: 2016-04-12 // CreatedBy: Jackie Lee /// <summary> /// 汽车移动日志代理 /// </summary> public class CarRunLogProxy : Runnable { private Car car; public CarRunLogProxy(Car car) { this.car = car; } public void Run() { Console.WriteLine("the car is begin to run..."); car.Run(); Console.WriteLine("the car stops running"); } } }
以下测试状况,效果代理
namespace FD.Pattern.ConsoleApplicationProxy { // CreatedOn: 2016-04-12 // CreatedBy: Jackie Lee /// <summary> /// 主程序 /// </summary> class Program { static void Main(string[] args) { Car c = new Car(); CarRunDateProxy cmdp = new CarRunDateProxy(c); cmdp.Run(); Console.WriteLine("========================="); CarRunLogProxy cmlp = new CarRunLogProxy(c); cmlp.Run(); Console.ReadKey(); } } }
效果:日志
为了实现能够同时组合多个代理,须要让代理传入的参数为抽象为接口Runnable,如下改进,如CarRunLogProxy将Car类型修改成Runnable接口,以下code
1 public class CarRunLogProxy : Runnable 2 { 3 private Runnable run; 4 public CarRunLogProxy(Runnable r) 5 { 6 this.run = r; 7 } 8 9 public void Run() 10 { 11 Console.WriteLine("the car is begin to run..."); 12 run.Run(); 13 Console.WriteLine("the car stops running"); 14 }
一样将CarRunDateProxy中的Car也改成Runnable接口,此时,能够实现任意组合进行记录信息。对象
先记录运行时间,现记录运行日志,在测试blog
1 Car c = new Car(); 2 CarRunDateProxy cmdp = new CarRunDateProxy(c); 3 Console.WriteLine("========================="); 4 5 Console.WriteLine("DateProxy, LogProxy"); 6 CarRunLogProxy cmlp = new CarRunLogProxy(cmdp); 7 cmlp.Run();
效果:继承
先记录日志,而后记录运行时间,则如:
CarRunLogProxy cmlp = new CarRunLogProxy(c); CarRunDateProxy cmdp = new CarRunDateProxy(cmlp); Console.WriteLine("========================="); Console.WriteLine("LogProxy,DateProxy"); cmdp.Run();