C#設計模式系列:代理模式(Proxy)


  代理模式提供了一個中介控制對某個對象的訪問。現實生活中,我們可能會用支票在市場交易中用來代替現金,支票就是賬戶中資金的代理。

1、代理模式簡介

1.1>、定義  

  代理模式(Proxy)定義:代理模式為客戶端程序提供一種中間層以控制對這個對象的訪問。

1.2>、使用頻率

   中高

2、代理模式結構

2.1>、結構圖

2.2>、參與者

  代理模式參與者:

  ◊ Proxy

    ° 維持一個引用,使得代理可以訪問Subject。

    ° 提供一個與Subject的接口相同的接口,這樣代理就可以替代Subject。

    ° 控制對Subject的訪問,並可能負責對Subject的創建和刪除。

  ◊ Subject:定義ConcreteSubject與Proxy的共用接口,從而在任何使用ConcreteSubject的地方都可以使用Proxy。

  ◊ ConcreteSubject:定義Proxy所代表的Subject。

  ◊ Client:維持一個對Subject的引用

  在代理模式中,由於Proxy與ConcreteSubject繼承同一接口,所以Client調用ConcreteSubject可以轉化為Client調用Proxy在調用ConcreteSubject,類Proxy為中間代理。

3、代理模式結構實現

  Subject.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.ProxyPattern.Structural
{
    public abstract class Subject
    {
        public abstract void Request();
    }
}

  ConcreteSubject.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.ProxyPattern.Structural
{
    public class ConcreteSubject : Subject
    {
        public override void Request()
        {
            Console.WriteLine("Called ConcreteSubject.Request()");
        }
    }
}

  Proxy.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.ProxyPattern.Structural
{
    public class Proxy : Subject
    {
        private ConcreteSubject _concreteSubject;

        public override void Request()
        {
            // Use 'lazy initialization'
            if (_concreteSubject == null)
            {
                _concreteSubject = new ConcreteSubject();
            }

            _concreteSubject.Request();
        }
    }
}

  Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DesignPatterns.ProxyPattern.Structural;

namespace DesignPatterns.ProxyPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create proxy and request a service
            Proxy proxy = new Proxy();
            proxy.Request();
        }
    }
}

  運行輸出:

Called ConcreteSubject.Request()
請按任意鍵繼續. . .

4、代理模式實踐應用

  IMath.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.ProxyPattern.Practical
{
    /// <summary>
    /// The 'Subject interface
    /// </summary>
    public interface IMath
    {
        double Add(double x, double y);
        double Sub(double x, double y);
        double Mul(double x, double y);
        double Div(double x, double y);
    }
}

  Math.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.ProxyPattern.Practical
{
    /// <summary>
    /// The 'ConcreteSubject' class
    /// </summary>
    public class Math : IMath
    {
        public double Add(double x, double y)
        {
            return x + y;
        }
        public double Sub(double x, double y)
        {
            return x - y;
        }
        public double Mul(double x, double y)
        {
            return x * y;
        }
        public double Div(double x, double y)
        {
            return x / y;
        }
    }
}

  MathProxy.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.ProxyPattern.Practical
{
    public class MathProxy : IMath
    {
        private Math _math = new Math();

        public double Add(double x, double y)
        {
            return _math.Add(x, y);
        }

        public double Sub(double x, double y)
        {
            return _math.Sub(x, y);
        }

        public double Mul(double x, double y)
        {
            return _math.Mul(x, y);
        }

        public double Div(double x, double y)
        {
            return _math.Div(x, y);
        }
    }
}

  Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DesignPatterns.ProxyPattern.Practical;

namespace DesignPatterns.ProxyPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create math proxy
            MathProxy proxy = new MathProxy();

            // Do the math
            Console.WriteLine("4 + 2 = " + proxy.Add(4, 2));
            Console.WriteLine("4 - 2 = " + proxy.Sub(4, 2));
            Console.WriteLine("4 * 2 = " + proxy.Mul(4, 2));
            Console.WriteLine("4 / 2 = " + proxy.Div(4, 2));
        }
    }
}

  運行輸出:

4 + 2 = 6
4 - 2 = 2
4 * 2 = 8
4 / 2 = 2
請按任意鍵繼續. . .

5、代理模式應用分析

  代理模式適用范圍很廣,不同的代理適合於不同的情形。

  ◊ 遠程代理為一個對象在不同的地址空間提供局部代表。

  ◊ 虛代理在需要創建開銷很大的對象時緩存對象信息。

  ◊ 保護代理控制對原始對象的訪問。保護代理用於對象應該有不同的訪問權限的時候。

  ◊ 智能指引取代了簡單指引,它在訪問對象時執行了一些附加操作。它的典型用途包括:對指向實際對象的引用計數,這樣當該對象沒有引用時,可以自動釋放。當第一次引用一個持久對象時,將它裝入內存。在訪問一個實際對象前,檢查是否已經鎖定了它,以確保其他對象不能改變它。

  代理模式特點:

  ◊ 代理模式在訪問對象時引入一定程度的間接性,可以隱藏對象的位置。

  ◊ 代理模式可以對用戶隱藏一種稱之為copy-on-write的優化方式。當進行一個開銷很大的復制操作的時候,如果復制沒有被修改,則代理延遲這一復制過程,這一可以保證只有當這個對象被修改的時候才對它進行復制。

6、代理模式與裝飾模式比較分析

  裝飾器模式關注於在一個對象上動態的添加方法,代理模式關注於控制對對象的訪問。

  裝飾器模式中Decorator和ConcreteComponent都實現Component,代理模式中Proxy和ConcreteSubject都實現Subject。使用這兩種模式,都可以很容易地在具體對象的方法前面或者后面加上自定義的方法。

  Proxy 可以對Client隱藏對象的具體信息,在使用代理模式時,常在Proxy中創建一個對象的實例。Proxy與ConcreteSubject之間的關系在編譯時就能確定。
  在使用裝飾模式時,常是將ConcreteComponent對象作為一個參數傳給ConcreteDecorator的構造器,Decorator在運行時遞歸的被構造。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM