Skip to content

代理模式

为某个对象提供一个代理,以控制对它的访问。

适合的场景

  • 延迟创建或加载一个资源(比如远程服务、图片等)

  • 添加权限控制、访问限制

  • 想在访问前后加点功能(日志、缓存、计时……)

基本结构

  1. Subject(抽象主题):定义真实对象和代理的公共接口

  2. RealSubject(真实对象):实现真正的业务逻辑

  3. Proxy(代理对象):控制访问、添加附加功能等

示例

csharp
// 抽象接口
public interface IDatabase
{
    void Query(string sql);
}

// 真实对象
public class RealDatabase : IDatabase
{
    public void Query(string sql)
    {
        Console.WriteLine($"执行SQL:{sql}");
    }
}

// 代理对象:权限控制
public class DatabaseProxy : IDatabase
{
    private readonly RealDatabase _realDb = new RealDatabase();
    private readonly string _userRole;

    public DatabaseProxy(string role)
    {
        _userRole = role;
    }

    public void Query(string sql)
    {
        if (_userRole != "admin")
        {
            Console.WriteLine("无权限访问数据库!");
        }
        else
        {
            Console.WriteLine("权限验证通过!");
            _realDb.Query(sql);
        }
    }
}

// 使用
IDatabase db = new DatabaseProxy("guest");
db.Query("SELECT * FROM Users;");  // 无权限访问!

db = new DatabaseProxy("admin");
db.Query("SELECT * FROM Users;");  // 权限验证通过 + 执行SQL

GDScript 示例

延迟加载资源

gdscript
# 抽象接口
class ImageLoader:
    func load_image(path: String) -> Texture2D:
        return null

# 真实对象
class RealImageLoader extends ImageLoader:
    func load_image(path: String) -> Texture2D:
        print("正在加载图片:%s" % path)
        return load(path)

# 代理对象:延迟加载
class ImageLoaderProxy extends ImageLoader:
    var real_loader: RealImageLoader
    var cache := {}

    func load_image(path: String) -> Texture2D:
        if path in cache:
            print("使用缓存图片:%s" % path)
            return cache[path]

        print("第一次加载,需要读取文件")
        real_loader = RealImageLoader.new()
        var tex = real_loader.load_image(path)
        cache[path] = tex
        return tex
        
# 使用
func _ready():
    var proxy = ImageLoaderProxy.new()
    proxy.load_image("res://icon.svg")  # 第一次加载
    proxy.load_image("res://icon.svg")  # 使用缓存