代理設計模式(一)靜態代理

概述

  代理在實際中應用場景主要爲,在對一個已有的類的方法,進行先後記錄一些操做。如當一個程序的方法運行時先後,添加一些日誌記錄或時間記錄,以測量該方法運行所耗的時間。代理的實現分靜態代理和動態代理,靜態代理主要可經過繼承與聚合進行實現。其中繼承的實現,主要是在對須要添加代理的類進行擴展,而後按各類需求進行擴展,但此種方式的缺點是,若是同時須要兩個代理功能,如先記錄時間,而後記錄日誌,則可先讓時間記錄繼承業務類,而後日誌記錄繼承時間記錄。但若是還須要先日誌後記錄時間,則又得再次寫一套繼承。如此,會致使類無快速增長。聚合的實現,則只須要將所實現同一接口的業務類對象進行前後傳遞便可。如下一步步在此,僅以簡單的例子,一步步實現代理的實現原理。測試

實現

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

相關文章
相關標籤/搜索