代理设计模式(一)静态代理

概述

  代理在实际中应用场景主要为,在对一个已有的类的方法,进行先后记录一些操做。如当一个程序的方法运行时先后,添加一些日志记录或时间记录,以测量该方法运行所耗的时间。代理的实现分静态代理和动态代理,静态代理主要可经过继承与聚合进行实现。其中继承的实现,主要是在对须要添加代理的类进行扩展,而后按各类需求进行扩展,但此种方式的缺点是,若是同时须要两个代理功能,如先记录时间,而后记录日志,则可先让时间记录继承业务类,而后日志记录继承时间记录。但若是还须要先日志后记录时间,则又得再次写一套继承。如此,会致使类无快速增长。聚合的实现,则只须要将所实现同一接口的业务类对象进行前后传递便可。如下一步步在此,仅以简单的例子,一步步实现代理的实现原理。测试

实现

1、静态代理实现  

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();

相关文章
相关标签/搜索