C#设计模式--代理模式(Proxy Pattern)

发布于:2024-12-18 ⋅ 阅读:(66) ⋅ 点赞:(0)

描述:

代理模式是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理模式在不直接访问实际对象的情况下,提供了对目标对象的间接访问。通过引入一个代理对象来间接操作实际对象,可以在不改变实际对象代码的前提下,增加额外的功能操作。

示例

// 定义主题接口
public interface ISubject
{
    void Request();
}

// 实现主题接口的具体类
public class RealSubject : ISubject
{
    public void Request()
    {
        Console.WriteLine("RealSubject:处理请求");
    }
}

// 代理类,也实现主题接口
public class Proxy : ISubject
{
    private RealSubject _realSubject;

    public Proxy(RealSubject realSubject)
    {
        this._realSubject = realSubject;
    }

    public void Request()
    {
        if (this.CheckAccess())
        {
            this._realSubject.Request();
            this.LogAccess();
        }
    }

    private bool CheckAccess()
    {
        Console.WriteLine("Proxy: 在发出真正的请求之前检查访问权限。");
        return true;
    }

    private void LogAccess()
    {
        Console.WriteLine("Proxy:记录请求的时间");
    }
}
ISubject
+void Request()
RealSubject
+void Request()
Proxy
-RealSubject _realSubject
+Proxy(RealSubject realSubject)
+void Request()
-bool CheckAccess()
-void LogAccess()

用处

• 访问控制:代理可以控制对真实对象的访问权限。
• 延迟初始化:代理可以在需要时才创建真实对象。
• 日志记录:代理可以在调用真实对象的方法前后添加日志记录。
• 性能优化:代理可以缓存结果,减少对真实对象的调用次数。

优点

• 增加灵活性:代理可以在不修改真实对象的情况下增加额外的功能。
• 保护目标对象:代理可以控制对目标对象的访问。
• 简化接口:代理可以简化复杂的接口。

缺点

• 增加复杂性:引入代理增加了系统的复杂性。
• 性能开销:代理可能会带来额外的性能开销。

案例1:远程代理

场景描述:客户端应用程序需要与远程服务器上的对象进行交互。为了简化网络通信,使用代理模式来处理网络请求。

代码示例

using System;

// 定义主题接口
public interface IRemoteService
{
    string GetData();
}

// 远程服务的具体实现
public class RemoteService : IRemoteService
{
    public string GetData()
    {
        // 模拟从远程服务器获取数据
        return "来自远程服务器的数据";
    }
}

// 远程代理
public class RemoteServiceProxy : IRemoteService
{
    private RemoteService _remoteService;

    public string GetData()
    {
        if (_remoteService == null)
        {
            _remoteService = new RemoteService();
        }
        Console.WriteLine("远程代理:正在获取数据...");
        return _remoteService.GetData();
    }
}

// 使用示例代码
public class Program
{
    public static void Main()
    {
        IRemoteService remoteService = new RemoteServiceProxy();
        string data = remoteService.GetData();
        Console.WriteLine(data);
    }
}

类图:

IRemoteService
+string GetData()
RemoteService
+string GetData()
RemoteServiceProxy
-RemoteService _remoteService
+RemoteServiceProxy()
+string GetData()

使用场景

• 分布式系统:客户端和服务器位于不同的物理位置,通过网络进行通信。
• 跨平台通信:客户端和服务器使用不同的编程语言或操作系统。

案例2:虚拟代理

场景描述:创建一个资源消耗较大的对象(如图像)时,使用代理模式来延迟对象的创建,直到真正需要时才创建。

代码示例

using System;

// 定义主题接口
public interface IImage
{
    void Display();
}

// 大型图像的具体实现
public class LargeImage : IImage
{
    private string _filename;

    public LargeImage(string filename)
    {
        _filename = filename;
        LoadFromDisk(_filename);
    }

    private void LoadFromDisk(string filename)
    {
        Console.WriteLine($"正在从磁盘加载 {_filename}");
    }

    public void Display()
    {
        Console.WriteLine($"正在显示 {_filename}");
    }
}

// 虚拟代理
public class ImageProxy : IImage
{
    private string _filename;
    private LargeImage _image;

    public ImageProxy(string filename)
    {
        _filename = filename;
    }

    public void Display()
    {
        if (_image == null)
        {
            Console.WriteLine("虚拟代理:图像尚未加载,现在开始加载...");
            _image = new LargeImage(_filename);
        }
        _image.Display();
    }
}

// 使用示例代码
public class Program
{
    public static void Main()
    {
        IImage image = new ImageProxy("example.jpg");
        // 图像尚未加载
        image.Display();
        // 图像已经加载
        image.Display();
    }
}

类图:

IImage
+void Display()
LargeImage
-string _filename
+LargeImage(string filename)
-void LoadFromDisk(string filename)
+void Display()
ImageProxy
-string _filename
-LargeImage _image
+ImageProxy(string filename)
+void Display()

使用场景

• 大型文件加载:图像、视频等大型文件的加载。
• 数据库连接:延迟建立数据库连接,直到需要执行查询时才连接。

案例3:保护代理

场景描述:控制对敏感对象的访问权限,确保只有授权用户才能访问对象的方法。

代码示例

using System;

// 定义主题接口
public interface IBankAccount
{
    void Deposit(int amount);
    void Withdraw(int amount);
}

// 银行账户的具体实现
public class BankAccount : IBankAccount
{
    private int _balance;

    public void Deposit(int amount)
    {
        _balance += amount;
        Console.WriteLine($"已存款 {amount},当前余额为 {_balance}");
    }

    public void Withdraw(int amount)
    {
        if (_balance >= amount)
        {
            _balance -= amount;
            Console.WriteLine($"已取款 {amount},当前余额为 {_balance}");
        }
        else
        {
            Console.WriteLine("余额不足");
        }
    }
}

// 保护代理
public class BankAccountProxy : IBankAccount
{
    private BankAccount _bankAccount;
    private bool _isAdmin;

    public BankAccountProxy(BankAccount bankAccount, bool isAdmin)
    {
        _bankAccount = bankAccount;
        _isAdmin = isAdmin;
    }

    public void Deposit(int amount)
    {
        _bankAccount.Deposit(amount);
    }

    public void Withdraw(int amount)
    {
        if (_isAdmin)
        {
            _bankAccount.Withdraw(amount);
        }
        else
        {
            Console.WriteLine("访问被拒绝:只有管理员才能取款");
        }
    }
}

// 使用示例代码
public class Program
{
    public static void Main()
    {
        IBankAccount bankAccount = new BankAccount();
        IBankAccount adminProxy = new BankAccountProxy(bankAccount, isAdmin: true);
        IBankAccount userProxy = new BankAccountProxy(bankAccount, isAdmin: false);

        adminProxy.Deposit(1000);
        adminProxy.Withdraw(500); // 管理员可以取款

        userProxy.Deposit(200);
        userProxy.Withdraw(100); // 普通用户无法取款
    }
}

类图:

IBankAccount
+void Deposit(int amount)
+void Withdraw(int amount)
BankAccount
-int _balance
+void Deposit(int amount)
+void Withdraw(int amount)
BankAccountProxy
-BankAccount _bankAccount
-bool _isAdmin
+BankAccountProxy(BankAccount bankAccount, bool isAdmin)
+void Deposit(int amount)
+void Withdraw(int amount)

使用场景

• 权限控制:银行账户、文件系统等需要严格权限控制的系统。
• 安全访问:防止未授权用户访问敏感数据。


网站公告

今日签到

点亮在社区的每一天
去签到