按照代理的创建时期,代理类可以分为两种:
静态:由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。
动态:在程序运行时运用反射机制动态创建而成。
RealSubject:真实角色,实现接口的类
Proxy:代理角色,包含对真实角色RealSubject的引用,进而操作真实对象。
Subject : 接口,是对象和它的代理共用
的接口,让RealSubject和Proxy具有一致性。
为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。并且,代理对象在执行真实对象操作时,附加其他操作,相当于对真实对象进行封装。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。
静态代理
package com.sz.demo;
public class TestStaticProxy {
//抽象接口
static interface Subject{
void sayHi();
void sayHello();
}
//真实角色
static class SubjectImpl implements Subject{
@Override
public void sayHi(){ //代理可以帮忙做的事
System.out.println("Hi");
}
@Override
public void sayHello(){
System.out.println("Hello");
}
}
//该角色的代理
static class SubjectImplProxy implements Subject{
private Subject target;
public SubjectImplProxy(Subject target){
this.target = target;
}
@Override
public void sayHi(){
System.out.println("say:");
target.sayHi();
}
@Override
public void sayHello(){
System.out.println("say:");
target.sayHello();
}
}
//测试
public static void main(String[] args){
Subject subject = new SubjectImpl();
Subject subjectProxy = new SubjectImplProxy(subject);
subjectProxy.sayHi();
subjectProxy.sayHello();
}
}
优点
- 代理使客户端不需要知道实现类是什么,怎么做的,而客户端只需知道代理即可(解耦合),对于客户端代码,可以应用工厂将它隐藏。
- 使用Proxy角色,使得耗时处理(生成实例)推迟。
- 在大型系统的初始化过程中,存在大量耗时处理,如果初始化暂时不会使用的功能,会使启动时间延长,所以使用代理模式,先初始化需要使用的功能。
缺点
- 增加了代码维护的复杂度:代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。
- 静态代理类只能为特定的接口(Service)服务。如想要为多个接口服务则需要建立很多个代理类。静态代理在程序规模稍大时就无法胜任了。