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

本文详细阐述了代理模式在代码实现中的应用,通过实例展示了如何利用代理模式为已有类添加额外功能,如记录运行时间与日志。文章进一步探讨了静态代理与动态代理的区别,并演示了如何通过接口实现灵活的代理组合。

概述

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

实现

一、静态代理实现  

1.基本的业务。假设有一个接口Runnable,现在让一个Car去实现它

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毫秒。

2.新增要求。现在要求在不改变Car的情况下,记录下Car的Run运行时间,Car的Run情况信息进行日志记录。以下使用聚合方式实现简单的静态代理

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接口,如下

 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接口,此时,可以实现任意组合进行记录信息。

先记录运行时间,现记录运行日志,在测试

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

 

转载于:https://www.cnblogs.com/dralee/p/5383107.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值