[设计模式] 结构型:代理模式,静态代理、动态代理(Proxy Pattern)

什么是代理模式

在公司上班,每月都要缴纳社保,你从来没有自己去社保中心缴纳过,都是由公司人力部门代你缴纳,人力小姐姐就是你的代理人,帮你做了这件事情。

火车票由铁路局印售,全国各地都有火车票代售点,你去最近的代售点就能买到你想要的车票,不用跑去铁路局,代售点就是铁路局的代理人,负责代理售卖火车票。

我具备做一件事情的能力,但是我又不想亲自做,就招个代理帮我做事情,这就是代理模式。

代理模式有两个角色:代理者、被代理者。代理者帮被代理者做事情,被代理者是幕后的老板,代理者只是个跑腿的。

代理模式应用到编程中,又被分为两个概念:静态代理、动态代理。两者区别:

  1. 静态代理:系统运行前,代理类就存在
  2. 动态代理:系统运行前,代理类不存在,运行后动态生成代理类

模式设计与实现

因为代理模式只涉及两个核心角色:代理者、被代理者。

所以模式设计相对简单,不管怎么设计,只要能完成代理任务,就都可以称之为代理模式。

具体到编程语言的实现,就各有各的方法,这里以Java语言为例,讲述代理模式的实现方法。

静态代理

原则是代理类事先就存在,那就只能自己手写代理类了。

因此,静态代理的Java代码实现,大概是这样的:

public interface Subject {
    void request();
}

// 被代理类
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("do something");
    }
}

// 代理类
public class RealSubjectProxy implements Subject {
    private RealSubject realSubject = new RealSubject();
    
    @Override
    public void request() {
        System.out.println("proxy do something");
        realSubject.request();
        System.out.println("proxy do something");
    }
}

前面说,代理者是帮被代理者做事情的,但是,看代码逻辑,虽然经过代理类,可最后感觉还是要劳烦被代理者自己把事情做了。

不知道读者有没有类似的感觉,反正我以前有过。后来想明白了,总结出代理模式的另一个特点:

代理者帮助被代理者做事情,可以添加一些辅助任务,但是核心任务必须通过被代理者去完成。

什么意思呢?就是说:

  1. 代售点可以帮铁路局收钱记账,但是卖票的核心任务还是由铁路局控制的
  2. 人力小姐姐可以帮你计算社保并代缴,但是核心的社保信息还得是你的

动态代理

JDK本身就提供有动态代理的机制,通过反射等手段,在系统运行的时候,动态生成代理类,还是比较方便的。

大概的代码如下:

public interface Subject {
    void request();
}

// 被代理类
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("do something");
    }
}

// 这个类的主要内容是"代理任务的执行逻辑",它不是代理类
public class ProxyLogic implements InvocationHandler {

    private Object realSubject;// 真实主题

    public RealSubjectDynamicProxy(Object realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("proxy do something");
        Object invoke = method.invoke(realSubject, args);
        System.out.println("proxy do something");
        return invoke;
    }
}

// 测试方法,展示如果生成代理类
public static void main(String[] args) {
    RealSubject realSubject = new RealSubject();
    // 代理类:动态生成的
    Subject proxy = (Subject) Proxy.newProxyInstance(
            RealSubject.class.getClassLoader(),
            new Class[]{Subject.class},
            new ProxyLogic(realSubject)
    );
}

动态代理不像静态代理那样,要把整个代理类都写一遍,但是核心的代理逻辑还是要写的。

为什么这么写,不是本文的重点,有兴趣的可以去了解java.lang.reflect.Proxy的实现逻辑。

总结

  1. 如果单纯只说设计模式,就只有“代理模式”这一说,具体到编程语言的实现,才有静态代理、动态代理这两种区分
  2. 静态代理写法简单,编码灵活度高,例如代理类方法名、被代理类哪些方法需要代理,都是可以自由选择的
  3. 动态代理写法稍微复杂,编码灵活度不高,但是编码规范度较高。如果被代理类方法较多,代理逻辑又是相同的,就适合使用动态代理,可以大幅度减少代码量
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值