7.代理模式(结构型)-灵析社区

菜鸟码转

七、 代理模式(结构型)

代理模式是一种结构型设计模式,它允许通过一个代理对象来控制对其他对象的访问。在代理模式中,代理对象与实际对象具有相同的接口,客户端无需知道实际对象的存在,只需要通过代理来访问实际对象。

代理模式通常分为以下两类:

  • 静态代理:在编译期就已经确定代理关系,并且代理类和被代理类的关系在代码中是固定的。静态代理的优点是简单易懂,缺点是需要为每个被代理类编写一个代理类;
  • 动态代理:在运行期根据需要动态生成代理类,从而避免了重复编写代理类的问题。Java 提供了反射机制和动态代理技术来实现动态代理。动态代理的优点是可以减少代理类的数量,缺点是实现比较复杂。

代理模式的应用场景

代理模式常见应用场景包括:

  • 远程代理:为了保护本地资源,将某些资源放在远程服务器上,然后通过代理来访问这些资源;
  • 虚拟代理:在访问大对象之前,先使用代理来创建一个占位符,当需要实际对象时再加载;
  • 安全代理:控制对实际对象的访问权限,例如只允许特定用户或角色访问;
  • 智能代理:在调用实际对象方法之前或之后,执行一些附加操作。例如,记录日志、缓存结果等。

静态代理

下面是一个简单的静态代理的 Java 示例代码:

  • 定义一个接口,代理类和被代理类都要实现这个接口
package cn.leetcode;

public interface Subject {

    void request();

}
  • 被代理类,实现了 Subject 接口
package cn.leetcode;

public class RealSubject implements Subject {
  
    public void request() {
        System.out.println("RealSubject request");
    }
  
}
  • 代理类,也实现了 Subject 接口,并且持有一个 RealSubject 对象的引用
package cn.leetcode;

public class Proxy implements Subject {
  
    private RealSubject realSubject;

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

    public void request() {
        System.out.println("Proxy request");
        realSubject.request();
    }
  
}
  • 客户端代码
package cn.leetcode;

public class Client {

    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        Proxy proxy = new Proxy(realSubject);
        proxy.request();
    }

}

输出:

Proxy request
RealSubject request

动态代理

代理模式是一种结构型设计模式,它允许通过代理对象来控制对真实对象的访问。代理对象通常充当客户端与真实对象之间的中介,可以在访问真实对象之前或之后执行一些额外的操作,例如缓存、验证、日志记录等。

动态代理是代理模式的一种实现方式,它允许在运行时创建代理对象,而不需要在编译时就确定代理对象的类型。动态代理通常使用 Java 的反射机制来实现,它能够自动生成代理对象的代码,从而简化了代理对象的实现过程。

  • 被代理的接口
package cn.leetcode;

public interface Subject {

    void brushQuestions();

}
  • 被代理对象
package cn.leetcode;


// 被代理类
public class Person implements Subject {

    private String name;

    public Person(String name) {
        this.name = name;
    }

    public void brushQuestions() {
        System.out.println(name + "正在努力刷题!");
    }

}
  • 动态代理类,实现 InvocationHandler 接口
package cn.leetcode;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;


public class DynaProxy implements InvocationHandler {

    /**
     * 被代理对象
     */
    private Object target;

    public DynaProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object obj;
        before();
        // 正在调用业务方法
        // 「方法对象」调用,参数 1:目标对象,参数 2:参数列表
        obj = method.invoke(target, args);
        after();
        return obj;
    }

    private void before() {
        System.out.println("准备合适的教程、力扣问题。");
    }

    private void after() {
        System.out.println("合适的总结。");
    }

}
  • 客户端
package cn.leetcode;

import java.lang.reflect.Proxy;

public class Client {

    public static void main(String[] args) {
        Person leetcoder = new Person("刷题爱好者");

        // Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
        // 动态生成代理对象(类加载器,被代理接口,InvocationHandler)
        ClassLoader classLoader = leetcoder.getClass().getClassLoader();
        Class<?>[] interfaces = leetcoder.getClass().getInterfaces();
        DynaProxy dynaProxy = new DynaProxy(leetcoder);
        Subject subject = (Subject) Proxy.newProxyInstance(classLoader, interfaces, dynaProxy);
        subject.brushQuestions();
    }

}


阅读量:2012

点赞量:0

收藏量:0