记录下学习设计模式-代理模式的写法。JDK使用版本为1.8版本。
意图:为其他对象提供一种代理以控制对这个对象的访问。
结构:
其中:
适用性:
以该UML类图实现静态代理模式示例。
package com.example.deesign_patterns.proxy.static_proxy;
//买火车票的接口
public interface SellTickets {
void sell();
}
package com.example.deesign_patterns.proxy.static_proxy;
//火车站类
public class TrainStation implements SellTickets{
@Override
public void sell() {
System.out.println("火车站卖票");
}
}
package com.example.deesign_patterns.proxy.static_proxy;
//代售点类
public class ProxyPoint implements SellTickets{
//声明火车站类对象,将TrainStation类(部分)聚合到ProxyPoint类(整体)里面
private TrainStation trainStation=new TrainStation();
@Override
public void sell() {
System.out.println("代理点收取一些服务费用");
trainStation.sell();
}
}
package com.example.deesign_patterns.proxy.static_proxy;
//测试类
public class Client {
public static void main(String[] args) {
//创建代售点类对象
ProxyPoint proxyPoint=new ProxyPoint();
//调用方法进行买票
proxyPoint.sell();
}
}
Java中提供了一个动态代理类Proxy,通过提供一个创建代理对象的静态方法(newProxyInstance方法)来获取代理对象。
package com.example.deesign_patterns.proxy.jdk_proxy;
//买火车票的接口
public interface SellTickets {
void sell();
}
package com.example.deesign_patterns.proxy.jdk_proxy;
//火车站类
public class TrainStation implements SellTickets {
@Override
public void sell() {
System.out.println("火车站卖票");
}
}
package com.example.deesign_patterns.proxy.jdk_proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//获取代理对象的工厂类
public class ProxyFactory {
//声明目标对象
private TrainStation trainStation=new TrainStation();
//获取代理对象的方法
public SellTickets getProxyObject(){
//返回代理对象
/*
newProxyInstance方法三个参数说明:
ClassLoader loader:类加载器,用于加载代理类。可以通过目标对象来获取类加载器
Class>[] interfaces:代理类实现的接口的字节码对象
InvocationHandler h:代理对象的调用处理程序
*/
SellTickets proxyObject = (SellTickets)Proxy.newProxyInstance(
trainStation.getClass().getClassLoader(),
trainStation.getClass().getInterfaces(),
new InvocationHandler() {
/*
Object proxy:代理对象。和proxyObject对象是同一个对象,在invoke方法中基本不用。
Method method:对接口中的方法进行封装的method对象
Object[] args:调用方法的实际参数,如果sell方法有参数,这里的参数就是sell方法的参数,本案例中sell没有参数
返回值:方法的返回值,本案例中sell方法没有返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代售点收取一定的服务费用(jdk动态代理)");
//执行目标对象的方法,通过反射的形式调用
Object obj = method.invoke(trainStation, args);
return obj;
}
}
);
return proxyObject;
}
}
package com.example.deesign_patterns.proxy.jdk_proxy;
//测试类
public class Client {
public static void main(String[] args) {
//获取代理对象
//1.创建代理工厂对象
ProxyFactory factory = new ProxyFactory();
//2.使用factory对象的方法获取代理对象
SellTickets proxyObject = factory.getProxyObject();
//3.调用卖票方法
proxyObject.sell();
}
}
如果pom.xml中有如下依赖,可直接使用cglib代理
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
如没有该依赖,添加这个依赖即可:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
package com.example.deesign_patterns.proxy.cglib_proxy;
//火车站类
public class TrainStation{
public void sell() {
System.out.println("火车站卖票");
}
}
package com.example.deesign_patterns.proxy.cglib_proxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
//代理对象工厂,用来获取代理对象
public class ProxyFactory implements MethodInterceptor {
//声明目标对象
private TrainStation trainStation=new TrainStation();
public TrainStation getProxyObject(){
//创建Enhancer对象,类似于JDK代理中的Proxy类
Enhancer enhancer=new Enhancer();
//设置父类的字节码对象
enhancer.setSuperclass(TrainStation.class);
//设置回调函数
enhancer.setCallback(this);
//创建代理对象
TrainStation proxyObject = (TrainStation) enhancer.create();
return proxyObject;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代售点收取一定的服务费用(cglib代理)");
//要调用目标对象的方法,使用反射的形式调用
Object obj = method.invoke(trainStation, objects);
return obj;
}
}
package com.example.deesign_patterns.proxy.cglib_proxy;
//测试类
public class Client {
public static void main(String[] args) {
//创建代理工厂对象
ProxyFactory factory=new ProxyFactory();
//获取代理对象
TrainStation proxyObject = factory.getProxyObject();
//调用代理对象中的sell方法卖票
proxyObject.sell();
}
}
jdk代理和cglib代理
动态代理和静态代理
优点:
缺点:
增加了系统的复杂度。