1.代理模式的介绍
代理模式(Proxy Pattern)也称为委托模式,是结构型设计模式的一种。在我们生活中代理模式是非常常见的,比如我们让同事帮忙买饭,房屋中介等都是一种代理模式。也就是让别人给自己干活。
2.代理模式的定义
为其他对象提供一种代理以控制对这个对象的访问。
3.代理模式的UML类图
代理模式- Subject: 抽象角色指真实角色和代理角色共有的接口。
- RealSubject: 真实角色需要实现抽象接口,定义真实角色所要实现的业务逻辑,以供代理角色调用。
- ProxySubject: 代理角色也需要实现抽象接口,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
4.静态代理模式的实现
通过让朋友代买水果,来实现代理模式:
第一步:先创建一个买水果的接口 (抽象角色)
package com.monkey.designmode.proxy;
/**
* Created by Monkey on 2020/5/9.
* Description: 买水果的接口
*/
public interface IBuyFruit {
void buyFruit();
}
第二步:实现买水果的接口 (真实角色)
package com.monkey.designmode.proxy;
/**
* Created by Monkey on 2020/5/9.
* Description: 具体的实现类,实现买水果的接口
*/
public class Monkey implements IBuyFruit {
@Override
public void buyFruit() {
System.out.println("我在果园里买水果");
}
}
第三步:创建一个代理对象 (代理角色)
package com.monkey.designmode.proxy;
/**
* Created by Monkey on 2020/5/9.
* Description:代理类 持有一个被代理者的引用
*/
public class BuyFruitProxy implements IBuyFruit {
private IBuyFruit iBuy;
public BuyFruitProxy(IBuyFruit iBuy) {
this.iBuy = iBuy;
}
@Override
public void buyFruit() {
iBuy.buyFruit();
}
}
客户端
package com.monkey.designmode.proxy;
public class ProxyClient {
public static void main(String[] args) {
IBuyFruit monkey = new Monkey();
BuyFruitProxy proxy = new BuyFruitProxy(monkey);
proxy.buyFruit();
}
}
这就是一个简单的静态代理模式,真实对象将方法的执行委托给代理对象去完成。
5.动态代理模式的实现
我们在静态代理的基础上实现动态代理模式,在这里我们需要创建一个动态处理器,帮我们创建一个代理类,而不需要静态代理中的 BuyFruitProxy
代理类了。动态代理是在运行时利用反射的机制动态生成代理者的对象。
创建一个动态代理类
package com.monkey.designmode.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* Created by Monkey on 2020/5/9.
* Description:动态代理类
*/
public class DynamicProxy implements InvocationHandler {
private Object object;
public DynamicProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//调用被代理对象的方法
Object result = method.invoke(object,args);
return result;
}
}
在动态代理类中我们声明一个Object
的引用,指向被代理类,我们调用被代理类的具体方法在invoke()
方法中执行。
客户端
package com.monkey.designmode.proxy;
import java.lang.reflect.Proxy;
public class ProxyClient {
public static void main(String[] args) {
IBuyFruit monkey = new Monkey();
//构造一个动态代理
DynamicProxy dynamicProxy = new DynamicProxy(monkey);
ClassLoader classLoader = monkey.getClass().getClassLoader();
//动态构造一个代理者
IBuyFruit proxy = (IBuyFruit) Proxy.newProxyInstance(classLoader,
new Class[]{IBuyFruit.class},dynamicProxy);
proxy.buyFruit();
}
}
Proxy.newProxyInstance()方法接受三个参数:
- ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法是固定的
- Class<?>[] interfaces:指定目标对象实现的接口的类型,使用泛型方式确认类型
- InvocationHandler:指定动态处理器,执行目标对象的方法时,会触发事件处理器的方法
使用动态代理很好的对代理者与被代理者进行解耦,使两者之间没有了直接的耦合;其中静态代理只能对给定的接口下的实现类做代理。而静态代理更符合面向对象的原则。
6.总结
通过引入代理对象的方式间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性。通过代理对象对原有的业务增强,而不影响原有的业务。
我们用通俗易懂的方式来理解下静态代理和动态代理的区别,我们在需要别人帮忙的时候,会提前给别人说好之后,才会给我们帮忙,这就是静态代理模式;而我们在需要帮忙的时候,直接告诉别人,现在就给我帮忙,这就是动态代理模式。
网友评论