2013年10月9日 星期三

Design Pattern : Proxy 代理

Design Pattern : Proxy 代理

Proxy 讓使用者不必接觸到實際的Class,而是藉由Proxy產生一個代理類別,使用者透過這個代理去進行操作即可。

底下的例子是某車廠的FOCUS車子(public class Focus : DPLib.ICar), 提供了最主要的功能:Drive 方法。

public class Focus : DPLib.ICar
{
        private DPLib.Color color;
        private String name;// = typeof(Focus).Name;
        private const String BRAND = "FORD";

        public Focus()
        {
            //取得當前類別名稱
            name = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name;
        }

        public DPLib.Color Color
        {
            get { return color; }
            set { color = value; }
        }
        public String Name
        {
            get { return name; }
            set { name = value; }
        }
        public void Drive()
        {
            Console.WriteLine("I am driving {0} {1} ({2})", color.ToString(), name, BRAND);
        }
    }

但是如果是隔年的新車,只有在每年度12/1的早上七點後才能出場駕駛(Drive), 所以Drive方法必須加上判斷, 這時候原來的車子就抗議了: 這是隔年新車的問題,為什麼在我身上加上這些判斷條件?
老闆也說:
千萬別再弄出個什麼 NEW Focus 或是 20XX Focus 花樣了, 駕駛的功能都已經有了,何必為了一個判斷再多做一次駕駛的功能。

這時候我們就可以透過Proxy去建立既有的Focus物件,以及對應去呼叫原有Focus的內容和方法。 至於判斷則可以加在Proxy Class裡面。

public class ProxyFocusNextYear : DPLib.ICar
    {
        /// <summary>
        /// 宣告 被代理的物件
        /// </summary>
        private DPLib.Focus focus;

        public ProxyFocusNextYear()
        {
            ///在建構時,建立被代理的 DPLib.Focus物件
            this.focus = new DPLib.Focus();
        }

        public String Name
        {
            get { return this.focus.Name; }
            set { this.focus.Name = value; }
        }
        public DPLib.Color Color
        {
            get { return this.focus.Color; }
            set { this.focus.Color = value; }
        }

        /// <summary>
        /// 代理類別的Drive方法
        /// 當年12/1後才提供駕駛,否則顯示無法駕駛的訊息
        /// </summary>
        public void Drive()
        {
            DateTime limitTime = DateTime.Parse((DateTime.Now.Year.ToString()+"-12-01 07:00:00"));
            if (DateTime.Now >= limitTime)
            {
                this.focus.Drive();
            }
            else
            {
                Console.WriteLine("{0} is not available for driving!", this.focus.Name);
            }
        }
    }

     ProxyFocusNextYear 裡面實際的內容和方法,都是源自原有Focus類別。

建立好代理之後, 如果有客戶要試駕隔年度的車,就由代理去做以下判斷吧:

DPLib.ICar newFocus = new ProxyFocusNextYear();
newFocus.Drive();


在本文測試的時候是十月,所以會得到以下結果:
Focus is not available for driving!


沒有留言:

張貼留言