代理模式

2023-10-06 10:02:35 浏览数 (2)

1.概要

代理设计模式是一种结构型设计模式,用于提供对象的替代品或占位符。在代理模式中,创建具有现有对象功能的对象,以向外部提供接口。代理控制着对原对象的访问,并允许在请求提交给对象前后进行一些处理。代理模式主要有三种形式:

  1. 静态代理:在编译期就已确定被代理的对象。代理类和被代理类共同实现一个接口或继承同一个类。
  2. 动态代理:在运行时通过反射机制实现,能够代理各种类型的对象。
  3. Cglib代理:属于动态代理的一种,能够在内存动态创建对象,无需实现接口。

使用场景

  1. 延迟初始化(虚拟代理):当有一个重量级的服务对象,但并不总是需要在程序启动时加载,可以使用代理来延迟初始化。代理对象在需要时才真正创建和加载原始对象,从而节省系统资源。
  2. 访问控制(保护代理):代理模式可以用于限制对某个对象的访问,实现访问控制和权限管理。只有经过授权的代理对象才能访问原始对象的某些功能。
  3. 权限控制:代理可以用来检查用户的权限,确保用户有权执行某些操作,例如数据库访问、文件操作等。
  4. 记录日志:代理可以用于记录方法的调用日志,包括方法的参数、返回值等信息,用于调试和监控应用程序。
  5. 缓存代理:代理可以缓存原始对象的结果,以提高性能。如果某个操作的结果已经被计算过,代理可以返回缓存的结果而不是重新计算。

2.详细内容

2.1静态代理

静态代理是代理设计模式的一种形式,它在编译期间就已经确定了被代理对象和代理对象。在静态代理中,代理类和被代理类共同实现同一个接口或者继承同一个父类。代理类负责控制对被代理对象的访问,可以在调用被代理对象的方法前后执行一些额外的操作,例如日志记录、性能监控、安全控制等。

静态代理的特点是代理类在编译期就已经存在,因此它的结构相对固定,不太灵活。代理类需要手动编写,通常一个代理类只能代理一个接口或者父类。

代码示例

代码语言:javascript复制
// 接口定义
public interface ISubject
{
    void Request();
}

// 具体实现类
public class RealSubject : ISubject
{
    public void Request()
    {
        Console.WriteLine("RealSubject handles the request.");
    }
}

// 代理类
public class Proxy : ISubject
{
    private RealSubject realSubject;

    public Proxy()
    {
        realSubject = new RealSubject();
    }

    public void Request()
    {
        // 可以在调用真实对象之前或之后执行一些额外操作
        Console.WriteLine("Proxy handles the request.");
        realSubject.Request();
    }
}

// 客户端代码
class Program
{
    static void Main(string[] args)
    {
        ISubject proxy = new Proxy();
        proxy.Request();
    }
}

2.2 动态代理

动态代理是代理设计模式的一种实现方式,允许在运行时创建代理对象,而无需预先编译好的类。它常用于实现横切关注点(cross-cutting concerns)的功能,比如日志、安全性检查、性能监测等。

代码语言:javascript复制
using System;
using System.Reflection;

public interface IService
{
    void DoSomething();
}

public class RealService : IService
{
    public void DoSomething()
    {
        Console.WriteLine("RealService is doing something.");
    }
}

public class ProxyGenerator
{
    public static T CreateProxy<T>(T target) where T : class
    {
        return (T)Activator.CreateInstance(typeof(T), new Proxy(target));
    }

    private class Proxy : DispatchProxy
    {
        private object _target;

        public Proxy(object target)
        {
            _target = target;
        }

        protected override object Invoke(MethodInfo targetMethod, object[] args)
        {
            Console.WriteLine($"Intercepting {targetMethod.Name}");
            var result = targetMethod.Invoke(_target, args);
            Console.WriteLine($"Finished intercepting {targetMethod.Name}");
            return result;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        IService realService = new RealService();
        IService proxyService = ProxyGenerator.CreateProxy(realService);
        proxyService.DoSomething();
    }
}

2.3 Cglib代理

它是一种基于字节码生成技术的代理模式。Cglib代理不要求被代理的类实现接口,而是通过生成被代理类的子类来实现代理。这种方式也是一种“动态代理”。

代码语言:javascript复制
using System;
using System.Reflection;
using System.Reflection.Emit;

public class ProxyGenerator
{
    public static T CreateProxy<T>() where T : class, new()
    {
        var dynamicMethod = new DynamicMethod("CglibProxy", typeof(T), Type.EmptyTypes, typeof(ProxyGenerator).Module);
        var ilGenerator = dynamicMethod.GetILGenerator();

        // Create a new instance of the target class
        ilGenerator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));

        // Return the new instance as the result of the method
        ilGenerator.Emit(OpCodes.Ret);

        // Create a delegate to the dynamic method
        var methodDelegate = (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>));

        // Return the proxy instance
        return methodDelegate();
    }
}

public class TargetClass
{
    public void DoSomething()
    {
        Console.WriteLine("TargetClass is doing something.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Create a Cglib proxy for TargetClass
        TargetClass proxy = ProxyGenerator.CreateProxy<TargetClass>();
        
        // Call the method on the proxy
        proxy.DoSomething();
    }
}

0 人点赞