設計模式之代理

—阿輝發表於2021-08-18

代理模式介紹

代理

代理模式 是一種結構型設計模式,讓你能夠提供物件的替代品或其佔位符。代理控制著對於原物件的訪問,並允許在將請求提交給物件前後進行一些處理。

其實說通俗點,就好比我們平時生活中的購買機票,火車票,我們以前的做法是去縣上或市區的每一個代理點去購買,你不需要關心代理點的工作人員去哪、購買車票,你只需要給錢說購買的地方,其餘的一切都交由他負責。那麼在這個購票的過程中,代理點的購票員就相當於是一種代理模式。

代理模式最常見的地方就是資料庫操作部分,對於資料庫的操作很多時候我們都在使用代理的模式來進行,比如我們常用的ORM其實說白了也是代理的一種特殊表現形式。

資料庫代理

代理模式結構

  • 服務介面 宣告服務介面,代理必須遵循該介面才能偽裝成服務物件。

  • 服務 類提供一些實用的業務邏輯。

  • 代理 類包含一個指向服務物件的引用成員變數。代理完成其任務(例如延遲初始化、記錄日誌、訪問控制和快取等)後會將請求傳遞給服務物件。通常情況下,代理會對其服務物件的整個生命週期進行管理。

  • 客戶端 能通過同一介面或代理進行互動,所以你可在一切需要服務物件的程式碼中使用代理。

代理模式應用場景

  • 延遲初始化
  • 訪問控制
  • 本地執行遠端服務(遠端代理)
  • 記錄日誌請求
  • 智慧引用

代理模式的實現方式

  • 如果沒有現成的服務介面,你就需要建立一個介面來實現代理和服務物件的可交換性。

  • 建立代理類,其中必須包含一個儲存指向服務的引用的成員變數(建立服務並對其整個生命週期進行管理,客戶端通過建構函式將服務傳遞給代理)。

  • 根據需求實現代理方法。在大部分情況下,代理在完成一些任務後應將工作委派給服務物件。

  • 可以考慮新建一個構建方法來判斷客戶端可獲取的是代理還是實際服務。(可在代理類中建立一個靜態方法,也可以建立工廠方法)

  • 可以考慮為服務物件提供延遲初始化操作

Demo

原始類提取的介面

    public interface ISubject 
    {
        void Request();
    }

原始類和代理類的實現

    /// <summary>
    /// 代理的物件  
    /// 在代理類中提前宣告並通過建構函式例項化
    /// </summary>
    public class RealSubject : ISubject
    {
        public void Request()
        {
            Console.WriteLine("列印原始的RealSubject");
        }
    }

    /// <summary>
    /// 代理類 ,實現了ISbuject介面
    /// </summary>
    public class Proxy : ISubject
    {
        private RealSubject _realSubject;
        public Proxy(RealSubject realSubject)
        {
            this._realSubject = realSubject;
        }

        public void Request()
        {
            if (CheakAccess())
            {
                _realSubject.Request();
                LogAcess();
            }
        }

        private bool CheakAccess() 
        {
            Console.WriteLine("Proxy:類  檢測驗證");
            return true;
        }

        private void LogAcess()
        {
            Console.WriteLine("Proxy類,主動輸出LogAcess");        
        }
    }

客戶端和驗證Main方法

    /// <summary>
    /// 驗證的客戶端
    /// 可接收實現了ISubject介面的類
    /// </summary>
    public class Client
    {
        public void ClientCode(ISubject subject)
        {
            subject.Request();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Client client = new Client();

            Console.WriteLine("開始");
            RealSubject realSubject = new RealSubject();
            client.ClientCode(realSubject);

            Console.WriteLine("-------------");
            Proxy proxy = new Proxy(realSubject);
            client.ClientCode(proxy);
            Console.ReadKey();
        }
    }

列印的結果

通過上面的資料庫訪問示意圖和練習的Demo程式碼,可以非常清楚的瞭解代理模式。在我們平時的業務開發過程中,可以多多留意是否有這樣的需求可以滿足代理模式的要求,那麼就大概率可以使用代理模式來實現或重構。

一個好的設計模式,是恰當好處的出現在了業務剛好需要它的時候才是最美妙的。

小寄語

人生短暫,我不想去追求自己看不見的,我只想抓住我能看的見的。

我是阿輝,感謝您的閱讀,如果對你有幫助,麻煩點贊、轉發 謝謝。

相關文章