定义
为其他对象提供一种代理,以控制对这个对象的访问。
- RealSubject 是被代理角色,为业务逻辑的具体执行者
- ProxySubject 是代理类
- Subject 是委托类和代理类的接口,图中标注的是接口,其实也可以是抽象类
使用场景
单是看上面的定义,可能会疑惑,为什么要代理呢?直接访问不可以吗?举现实的例子就比较好理解。NBA中的球员转会。当球员面临转会时,繁杂的事情可以由经纪人代为处理。球员只需要从诸多报价球队中,选择自己满意的,具体的转会费、薪资谈判,都交给经纪人去搞定。又如邀请明星演出,只需要联系明星的经纪人即可。明星只需要负责演出,具体接哪些通告,由经纪人负责就好了。例子可能不是很恰当,理解意思就好。
网上看到一个例子,觉得不错:我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品。关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,“委托者”对我们来说是不可见的;其次,微商代理主要以朋友圈的人为目标客户,这就相当于为厂家做了一次对客户群体的“过滤”。我们把微商代理和厂家进一步抽象,前者可抽象为代理类,后者可抽象为委托类(被代理类)。
具体到java程序中,我们可以在代理类中,加入通用的日志打印功能,而具体的实现类,主需要关注业务逻辑即可。AOP使用的就是动态代理。
优点
- 职责清晰
为拖累只需关注业务逻辑的实现,非业务逻辑,后期通过代理类实现即可。 - 高扩展性
不管委托类如何变化,由于接口是不变的,因为,我们的代理类无需做任何修改。 - 智能化
动态代理
分类
如果按照代理的创建时期,代理类可以分为两种:静态代理、动态代理。
- 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
- 动态代理:在程序运行时,运用反射机制动态创建而程。
静态代理
静态代理实现比较简单。只需要创建1个接口,2个实现类即可。
接口类:
public interface Subject {
public void doSometing();
}
委托类
public class RealSubject implements Subject{
@Override
public void doSometing() {
System.out.println("I'm workding");
}
}
代理类
public class ProxySubject implements Subject{
private Subject subject = null;
public ProxySubject(Subject _subject){
this.subject = _subject;
}
@Override
public void doSometing() {
this.subject.doSometing();
}
}
上面就是一个简单的静态代理。为了体现代理的作用,我们要求,在执行doSomething方法前,打印执行类的信息。 创建一个客户端,模拟场景:
public class Client {
public static void main(String args[]){
Subject subject = new RealSubject();
ProxySubject proxy = new ProxySubject(subject);
proxy.doSometing();
}
}
运行结果如下:
model.proxy.RealSubject
I'm workding
通过代理类,可以实现在执行doSomething方法前打印类名。试想,如果对于Subject接口,有很多实现类,我们就无需关注打印实现类的信息,而只需实现doSomething方法。
动态代理
动态代理,是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。相对于静态代理,动态代理相对复杂。在一下篇文章中具体介绍。