1. 程式人生 > >用心理解設計模式——代理模式 (Proxy Pattern)

用心理解設計模式——代理模式 (Proxy Pattern)

前置文章: 用心理解設計模式——設計模式的原則 

設計模式相關程式碼已統一放至 我的 Github

 

一、定義

  結構型模式之一。

  Provide a surrogate or placeholder for another object to control acess to ot.

(為其他物件提供一種代理,以控制對這個物件的訪問)

二、結構解析

  代理模式的一般結構有三種角色:抽象主題、真實主題(被代理者)、代理者。

  抽象主題,負責定義和宣告真實主題要被代理的業務方法介面。

  真實主題,繼承抽象主題,實現自己真實的業務方法介面。

  代理者,也繼承抽象主題,擁有與真實主題(被代理者)相同的要被代理的業務方法介面, 從外觀上看代理者與被代理者似乎一樣。代理者內部依賴真實主題,實現這些業務方法介面時,最終呼叫了真實主題(被代理者)的業務方法,但可以在預先或之後進行了一些額外的處理。

三、評價

  代理模式封裝了客戶訪問或控制真實主題(被代理者)的過程,充當代理作用,解除了客戶和真實主題之間的直接耦合。

  各自職責變得清晰,符合開閉原則, 非常易擴充套件。

  在真實主題不唯一, 但代理過程相同時,只需新增真實主題類即可(對擴充套件開放),而不用修改已有的代理類和已有的真實主題類(對修改關閉)。

  在真實主題唯一, 但代理過程不同時,只需新增滿足需求的代理類(對擴充套件開放),而不用修改已有的代理類和已有的真實主題類(對修改關閉)。

  在真實主題唯一, 代理過程也不同時,可以同時擴充套件且不用修改已有的代理類和已有的真實主題類。

四、實現

namespace Proxy
{
    //抽象主題
    public abstract class Subject
    {
        //定義和宣告真實主題要被代理的業務方法介面
        public abstract void DoSth();
    }

    //真實主題
    public class RealSubject : Subject
    {
        //實現業務方法介面,真實要做的事情。
        public override void DoSth(){}
    }

    //代理者
    public class Proxy : Subject
    {
        //內部依賴真實主題
        private Subject subject = new RealSubject();

        //代理者擁有與真實主題(被代理者)
        public override void DoSth()
        {
            //額外的預先操作
            this.Before();
            //最終呼叫真實主題的業務方法
            this.subject.DoSth();
            //額外的後續操作
            this.After();
        }

        private void Before() { }
        private void After() { }
    }

    public class Client
    {
        static public void Main()
        {
            Proxy proxy = new Proxy();
            proxy.DoSth();
        }
    }
}

五、真實主題和代理過程擴充套件

namespace Proxy.ExpandBoth
{
    public abstract class Subject
    {
        public abstract void DoSth();
    }

    //真實主題A
    public class RealSubjectA : Subject
    {
        public override void DoSth() { }
    }

    //真實主題B
    public class RealSubjectB : Subject
    {
        public override void DoSth() { }
    }

    //代理X
    public class ProxyX : Subject
    {
        //在構造代理者時確定代理哪個真實主題
        private Subject subject = null;
        public ProxyX(Subject subject)
        {
            this.subject = subject;
        }

        public override void DoSth()
        {
            this.BeforeX();
            this.subject.DoSth();
            this.AfterX();
        }

        private void BeforeX() { }
        private void AfterX() { }
    }

    //代理Y
    public class ProxyY : Subject
    {
        //在構造代理者時確定代理哪個真實主題
        private Subject subject = null;
        public ProxyY(Subject subject)
        {
            this.subject = subject;
        }

        public override void DoSth()
        {
            this.BeforeB();
            this.subject.DoSth();
            this.AfterB();
        }

        private void BeforeB() { }
        private void AfterB() { }
    }

    public class Client
    {
        static public void Main()
        {
            RealSubjectA realSubjectA = new RealSubjectA();
            RealSubjectB realSubjectB = new RealSubjectB();

            //X代理真實主題A
            ProxyX proxyXA = new ProxyX(realSubjectA);
            proxyXA.DoSth();
            //X代理真實主題B
            ProxyX proxyXB = new ProxyX(realSubjectB);
            proxyXB.DoSth();
            //Y代理真實主題A
            ProxyY proxyYA = new ProxyY(realSubjectA);
            proxyYA.DoSth();
            //Y代理真實主題B
            ProxyY proxyYB = new ProxyY(realSubjectB);
            proxyYB.DoSth();
        }
    }
}

六、動態代理

  TODO