一、定义
为其他对象提供一种代理,以控制对该对象的访问。
二、简图
三、分类
代理模式分静态代理和动态代理两种模式
四、代码实例
需求:原告通过律师向法院进行申诉
分析:
1、静态代理实现
A:创建申诉接口IAppeal
/**
* 申诉接口
* @author petergee
* @date 2018/3/15
*/
public interface IAppeal {
//申诉方法
void appeal();
}
B:创建原告类实现接口
/**
* 原告类
*
* @author petergee
* @date 2018/3/15
*/
public class Plaintiff implements IAppeal {
private String mName;
public Plaintiff(String name) {
this.mName = name;
}
@Override
public void appeal() {
System.out.println("I am " + mName + ",i wanna appeal");
}
}
C:创建律师类作为代理,同时实现申诉接口,并代理原告申诉
/**
* 律师类
*
* @author petergee
* @date 2018/3/15
*/
public class Lawyer implements IAppeal {
private Plaintiff mPlaintiff;
public Lawyer(Plaintiff plaintiff) {
this.mPlaintiff = plaintiff;
}
@Override
public void appeal() {
mPlaintiff.appeal();
}
}
D:测试类
/**
* 测试类
* @author petergee
* @date 2018/3/15
*/
public class StaticProxyClassTest {
public static void main(String[] args) {
//创建原告实例
Plaintiff plaintiff = new Plaintiff("ThreeZhang");
Lawyer lawyer = new Lawyer(plaintiff);
lawyer.appeal();
}
}
E:结果
F:分析
优点:
通过代理类可以对被代理类进行封装,实现被代理类需求
缺点:
被代理类和代理类都要实现同一个接口,当有多个被代理类时需要实现多个接口,会导致代理类变得复杂
2、动态代理实现
由于JDK中帮我们提供了生成动态代理的API
static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
下面使用该API实现上述需求
A:创建动态代理申诉接口DynamicIAppeal
/**
* 申诉接口
* @author petergee
* @date 2018/3/15
*/
public interface DynamicIAppeal {
//申诉方法
void appeal();
}
B:创建原告类实现DynamicIAppeal
/**
* 动态代理原告类
*
* @author petergee
* @date 2018/3/15
*/
public class DynamicPlaintiff implements DynamicIAppeal {
private String mName;
public DynamicPlaintiff(String name){
this.mName=name;
}
@Override
public void appeal() {
System.out.println("i am "+mName+" i wanna appeal");
}
}
C:创建动态代理律师类使用Proxy.newProxyInstance方法获取被代理的类实例
package net.petergee.designmodedemo.designmode.proxy.dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理律师类
*
* @author petergee
* @date 2018/3/15
*/
public class DynamicLawyer {
private Object mObject;
/**
* Object类型对象通过构造传递 ,更加灵活
* @param o
*/
public DynamicLawyer(Object o) {
this.mObject = o;
}
/**
* 获取动态代理对象
* 参数:classLoader 、interface、InvocationHandler
*/
public Object getDynamicProxy() {
return Proxy.newProxyInstance(mObject.getClass().getClassLoader(), mObject.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object value = method.invoke(mObject, args);
return value;
}
});
}
}
可见动态代理构造方法中并没有将对象类型固定,而是提供了Object类型,可以代理多种类型被代理类
,动态代理DynamicLawyer中没有 实现DynamicIAppeal接口而是通过JDK提供的方法来获取被代理类对象,相比静态代理更加灵活
D:测试类
package net.petergee.designmodedemo.designmode.proxy.dynamicProxy;
/**动态代理测试类
* @author petergee
* @date 2018/3/15
*/
public class DynamicProxyTest {
public static void main(String[] args) {
DynamicIAppeal plaintiff = new DynamicPlaintiff("FourLi");
DynamicIAppeal proxy = (DynamicIAppeal) new DynamicLawyer(plaintiff).getDynamicProxy();
proxy.appeal();
}
}
E:结果
F:分析
(1)、动态代理代理类不必实现被代理类接口,可以使用JDK提供的动态代理API获取被代理对象
(2)、被代理类一定要实现一个接口,否则不起作用
代码Demo仓库地址:https://github.com/PeterGee/DesignModeDemo
参考:https://www.cnblogs.com/cenyu/p/6289209.html)