Proxy -- 代理模式 : 为其他对象提供一种代理以控制对这个对象的控制 (静态代理)
特点: 实现相同的接口
// 公共接口 -- 代理角色
public interface Subject{
void request();
}
// 真正实体 -- 真实角色
public class RealSubject implements Subject{
private String name;
public RealSubJect(String name) {
this.name = name;
}
@Override
public void request() {
System.out.println(name + "画画");
}
}
// 代理类 -- 代理角色
public class Proxy implements Subject {
private String name;
public Proxy(String name) {
this.name = name;
}
@Override
public void request() {
if(realSubject == null) {
realSubject = new RealSubject(name);
}
realSubject.request();
}
}
// 测试类
public class ProxyTest {
public static void main(String[] args) {
Proxy proxy = new Proxy("test");
proxy.request();
}
}
JDK --- 动态代理: JDK的动态代理是基于接口的,必须实现了某一个或多个任意接口才可以被代理,
并且只有这些接口中的方法会被代理。
interface Subject {
public void doSomething();
}
class RealSubject implements Subject {
public void doSomething() {
System.out.println("call doSomething");
}
}
// 代理类
class ProxyHandler implements InvocationHandler {
private Object tar;
// 绑定委托对象,并返回代理类
public Object bind() {
this.tar = tar;
// 绑定该类实现的所有接口,取得代理类
return Proxy.newProxyInstance(tar.getClass().getClassLoader(), tar.getClass.getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null; // 被代理的类型为Object基类
// 这里就可以进行所谓的AOP编程了
// 在调用具体函数方法前,执行功能处理
result = method.invoke(tar, args);
return result;
}
}
// 测试类
public class Test {
public static void main() {
ProxyHandler proxy = new ProxyHandler();
// 绑定该类实现的所有接口
Subject sub = (Subject)proxy.bind(new RealSubject);
sub.doSomething();
}
}
在调用过程中使用了通用的代理类包装了RealSubject实例,然后调用了Jdk的代理工厂方法实例化了一个具体的代理类。
最后调用代理的doSomething方法,还有附加的before、after方法可以被任意复用(只要我们
在调用代码处使用这个通用代理类去包装任意想要需要包装的被代理类即可)。
当接口改变的时候,虽然被代理类需要改变,但是我们的代理类却不用改变了。
这个调用虽然足够灵活,可以动态生成一个具体的代理类,而不用自己显示的创建一个实现具体接口的代理类。
适配器模式和代理模式区别:
适配器模式: 因为新旧接口不一致导致出现了客户端无法得到满足的问题,
但是,由于旧的接口是不能完全被重构,因为实现此接口的一些服务还在被使用,所以需要把新的接口转换为旧接口,
实现这个装换的类就是抽象意义上的转换器。
代理模式: 都是继承的相同的接口,为了屏蔽对原来对象的访问,并可以在代理对象的时候进行处理。