首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 設計模式精講:代理模式

     編輯:關於C#

一、代理模式:為對象提供替身以控制訪問

代理模式為某對象提供一個代理,由代理控制對原對象的引用。代理在客戶端與目標對象間起中介作用,適用於客戶端不想或不能直接引用目標對象的場景。

二、代理的多種類型

類型用途
遠程代理為不同地址空間的對象提供本地代表(如 Web Service、.NET Remoting)
虛擬代理按需創建資源消耗大的對象(如大圖片延遲加載)
Copy-on-Write 代理延遲複製操作至真正需要時
保護代理控制訪問權限,不同用戶不同權限
Cache 代理暫存操作結果供多客戶端共享
防火牆代理保護目標免受惡意訪問
同步化代理多用戶並發訪問同一對象無衝突
智能引用代理引用時執行額外操作(如計數、鎖定)

最常見的是:虛擬、遠程、智能引用、保護代理。

三、經典類比:孫悟空扮高翠蘭

《西遊記》中悟空變作高翠蘭模樣會見豬八戒,完美詮釋保護代理:

  • 高翠蘭神貌(抽象介面)與本人(真實主題)分離 → 符合開閉原則
  • 悟空實現「高翠蘭神貌」介面,代替本人會見八戒 → 代理角色
  • 八戒無法分辨真假 → 客戶端不可區分代理與真實對象

悟空代理結構圖

對象交互圖

四、標準結構與示例代碼

代理模式類圖

三大角色:抽象主題、代理主題(持有真實主題引用、控制訪問、可在前後執行額外邏輯)、真實主題。

// Proxy pattern -- Structural example
using System;

abstract class Subject { abstract public void Request(); }

class RealSubject : Subject {
    override public void Request() { Console.WriteLine("Called RealSubject.Request()"); }
}

class Proxy : Subject {
    RealSubject realSubject;
    override public void Request() {
        if (realSubject == null) realSubject = new RealSubject(); // 惰性初始化
        preRequest();
        realSubject.Request();
        postRequest();
    }
    public void preRequest() { Console.WriteLine("PreRequest."); }
    public void postRequest() { Console.WriteLine("PostRequest."); }
}

public class Client {
    public static void Main() {
        Proxy p = new Proxy(); p.Request();
    }
}

五、各類代理的結構特點

  • 遠程代理:隱藏網絡細節,代理承擔通信工作。
  • 虛擬代理:必要時才加載真實對象,可優化加載過程。
  • 保護代理:運行時檢查權限,決定是否轉發調用。
  • 智能引用代理:訪問時執行內務操作(計數、日誌等)。

六、實戰:跨 AppDomain 遠程代理

// Proxy pattern -- Real World example
using System; using System.Runtime.Remoting;

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

class Math : MarshalByRefObject, 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; }
}

class MathProxy : IMath {
    Math math;
    public MathProxy() {
        AppDomain ad = AppDomain.CreateDomain("MathDomain", null, null);
        ObjectHandle o = ad.CreateInstance("Proxy_RealWorld", "Math", false,
            System.Reflection.BindingFlags.CreateInstance, null, null, null, null, null);
        math = (Math)o.Unwrap();
    }
    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); }
}

public class ProxyApp {
    public static void Main() {
        MathProxy p = new MathProxy();
        Console.WriteLine("4 + 2 = {0}", p.Add(4, 2));
        Console.WriteLine("4 - 2 = {0}", p.Sub(4, 2));
        Console.WriteLine("4 * 2 = {0}", p.Mul(4, 2));
        Console.WriteLine("4 / 2 = {0}", p.Div(4, 2));
    }
}

代理在構造函數中於獨立 AppDomain 創建真實對象,客戶端透明調用,實現隔離與安全。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved