一、什么是代理模式
Proxy模式又叫做代理模式,是构造型的设计模式之一,它可以为其他对象提供一种代理(Proxy)以
控制对这个对象的访问。
所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目标
类交互,而代理一般在交互的过程中(交互前后),进行某些特别的处理。
二、代理模式的结构
三、代理模式的角色及职责
subject(抽象主题角色):
真实主题与代理主题的共同接口。
RealSubject(真实主题角色):
定义了代理角色所代表的真实对象。
Proxy(代理主题角色):
含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真实主题对象之前或者之后执行某些操作,
而不是单纯返回真实的对象。
四、动态代理
1. InvocationHandler 接口
InvocationHandler
是代理实例的调用处理程序 实现的接口。
每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,
将对方法调用进行编码并将其指派到它的调用处理程序的 invoke
方法。
2. invoke方法
在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
3. Proxy.newProxyInstance();
五、实例实现
静态代理模式:
//1.真实主题与代理主题之间的共同接口:
public interface Subject {
public void sailBook();
}
//2.真实主题
public class RealSubject implements Subject{
public void sailBook() {
System.out.println("卖书");
}
}
//3.代理主题
public class ProxySubject implements Subject{
private RealSubject realSubject;//和proxySubject相关联
/*
public void setRealSubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
*/
@Override
public void sailBook() {
discuont();
if(realSubject == null){
realSubject = new RealSubject();
}
this.realSubject.sailBook();//调用当前对象的卖书方法
give();
}
public void discuont(){
System.out.println("买书打折!");
}
public void give(){
System.out.println("买书送代金券");
}
}
//4.测试
public class TestProxy {
public static void main(String[] args) {
// RealSubject realSubject = new RealSubject();
ProxySubject proxySubject = new ProxySubject();
// proxySubject.setRealSubject(realSubject);
proxySubject.sailBook();
}
}
动态代理模式:
package com.dzg.learn.proxy.dynamicproxy;
import com.dzg.learn.proxy.RealSubject;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MyHandler implements InvocationHandler {
private RealSubject realSubject;
public void setRealSubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
/**
*
* @param proxy 在其上调用方法的代理实例
* @param method 对应于在代理实例上调用的接口方法的 Method 实例。
* Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
* @param args 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。
* 基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。
* @return
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
Object result = null;
discuont();
try {
result = method.invoke(realSubject,args);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
give();
return result;
}
public void discuont(){
System.out.println("动态买书打折!");
}
public void give(){
System.out.println("动态买书送代金券");
}
}
//测试:
package com.dzg.learn.proxy.dynamicproxy;
import com.dzg.learn.proxy.RealSubject;
import com.dzg.learn.proxy.Subject;
import java.lang.reflect.Proxy;
public class TestDynamicProxy {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
MyHandler myHandler = new MyHandler();
myHandler.setRealSubject(realSubject);
/*
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
loader - 定义代理类的类加载器
interfaces - 代理类要实现的接口列表
h - 指派方法调用的调用处理程序
返回:
一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口
*/
Subject proxySubject = (Subject) Proxy.newProxyInstance(RealSubject.class.getClassLoader(),
realSubject.getClass().getInterfaces(),myHandler);
proxySubject.sailBook();
}
}
动态代理模式不需要实例化一个代理模式的对象!