五、代理模式——奉天子命诸侯

本文详细介绍了代理模式的概念及其应用场景,包括静态代理和动态代理的实现方式。通过实例展示了如何利用代理模式进行功能增强,同时探讨了代理模式在软件开发中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


设计模式是面向问题、场景而总结产生的设计思路。是解决问题的套路。23 种经典的设计模式。它们又可以分为三大类:创建型、结构型、行为型。

结构型 包含了 代理模式、 桥接模式、 装饰器模式、适配器模式、门面模式、组合模式、 享元模式。

代理模式

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。现实中如租房中介、售票黄牛、婚介、经纪人、太监都是代理。

1. 为什么使用代理模式

当需要扩展功能时,在原有业务功能执行的前后加入一些公共的服务。例如我们想给某个类方法加入缓存、日志、权限控制、资源开和释放、事务管理等都可以通过代理来实现功能扩张增强。代理模式符合开闭原则原则——对修改关闭,对扩展开放。

2. 静态代理

2.1 通过接口实现静态代理

代理模式是一种组合关系,将委托类组合在代理类内部,通过代理方法增加额外的功能来扩展功能。在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。

RealWorker 类 是具体实现了compute方法的类,而WorkerProxy 持有了RealWorker 对象。在对外宣称的compute()服务时,WorkerProxy 可以“添油加醋”增加log();clean();等方法,这样能实现对委托对象的功能增强。

public interface Worker {
    void compute();
}

public class RealWorker implements Worker{
    @Override
    public void compute() {
        System.out.println("real worker is computing");
    }
}

public class WorkerProxy implements Worker {

    private Worker realworker;

    public void setRealworker(Worker realworker) {
        this.realworker = realworker;
    }

    public WorkerProxy(Worker realworker) {
        this.realworker = realworker;
    }

    private void log(){
        System.out.println("log something");
    }

    private void clean(){
        System.out.println("release resources");
    }

    @Override
    public void compute() {
        log();
        realworker.compute();
        clean();
    }

}

经过测试运行。

public class Main {
    public static void main(String[] args) {
        Worker worker = new WorkerProxy(new RealWorker());
        worker.compute();
    }
}

运行结果如下

log something
real worker is computing
release resources

2.2 通过继承实现静态代理

当RealWorker类已经完成编写了,并没有提前实现Worker接口。那么可以通过继承的方法,来实现增强。

public class WorkerProxy2 extends RealWorker {

    private void log() {
        System.out.println("log something");
    }

    private void clean() {
        System.out.println("release resources");
    }

    @Override
    public void compute() {
        log();
        super.compute();
        clean();
    }
}

3. 动态代理

静态代理需要通过编码的方式实现,而动态代理可以在运行时动态创建。Java反射语法提供了动态代理所需要的功能。

  • 定义Worker接口及实现类
public interface Worker {
    void compute();
}

public class RealWorker implements Worker {

    public void compute() {
        System.out.println("real worker is computing");
    }

}
  • 定义一个InvocationHandler,实现invoke(Object proxy, Method method, Object[] args)方法,在反射调用方法时可以进行增强。
public class WorkerInvocationHandler implements InvocationHandler {

    private Object o;

    public WorkerInvocationHandler(final Object o) {
        this.o = o;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("prepare");
        Object res = method.invoke(o, args);
        System.out.println("clean");
        return res;
    }
}
  • 编写测试类
public class Main {
    public static void main(String[] args) {

        Worker realWorker = new RealWorker();
        //Worker realWorker2 = new RealWorker2();

        InvocationHandler handler = new WorkerInvocationHandler(realWorker);
        ClassLoader loader = realWorker.getClass().getClassLoader();
        Class[] interfaces = realWorker.getClass().getInterfaces();

        Worker proxyworker = (Worker) Proxy.newProxyInstance(loader, interfaces, handler);

        proxyworker.compute();
    }
}

运行结果

prepare
real worker is computing
clean

总结

代理模式常用于对功能需求进行增强,增加一些非业务性的功能,比如监控、统计、鉴权、限流、事务、幂等、日志。Spring AOP 基于动态代理实现了面向切面编程,对方法进行纵向增强,再通过编织,将软件的复杂性大大降低。其实RPC也是使用代理模式思想,在本地端代理了远程对象,使得远程方法调用如同本地调用一样。
  
设计模式系列在github上有一个开源项目,主要是本系列博客的demo代码。https://github.com/forestnlp/designpattern
如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。
您的支持是对我最大的鼓励。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟空学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值