目录
场景
代码实现
编辑
解析
定义
代理模式调用示意图
代理模式的特点
本质
编辑何时选用
场景
我有一个订单类,包含订单数、用户名和商品名,有一个订单接口包含了对订单类的getter和setter
现在有一个需求,a创建的订单只能a修改,其他人无权修改
代码实现
定义OrderApi接口
package day10代理模式;
public interface OrderApi {
public String getProductName();
void setProductName(String productName,String user);
public String getOrderUser();
public void setOrderUser(String orderUser,String user);
public int getOrderNum();
void setOrderNum(int orderNum,String user);
}
Order类,实现订单接口
package day10代理模式;
public class Order implements OrderApi{
private String productName;
private int orderNum;
private String orderUser;
public Order(String productName, int orderNum, String orderUser) {
this.productName = productName;
this.orderNum = orderNum;
this.orderUser = orderUser;
}
@Override
public String toString() {
return "Order{" +
"productName='" + productName + '\'' +
", orderNum=" + orderNum +
", orderUser='" + orderUser + '\'' +
'}';
}
public void setOrderUser(String orderUser) {
this.orderUser = orderUser;
}
public void setProductName(String productName) {
this.productName = productName;
}
@Override
public int getOrderNum() {
return orderNum;
}
@Override
public void setOrderNum(int orderNum,String user) {
this.orderNum = orderNum;
}
@Override
public String getProductName() {
return productName;
}
@Override
public void setProductName(String productName, String user) {
this.productName = productName;
}
@Override
public String getOrderUser() {
return this.orderUser;
}
@Override
public void setOrderUser(String orderUser, String user) {
this.orderUser = orderUser;
}
}
现在创建一个代理类
package day10代理模式.java中的代理类;
import day10代理模式.Order;
import day10代理模式.OrderApi;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/**
* 使用java中的动态代理
*/
public class DynamicProxy implements InvocationHandler {
/**
* 被代理的对象
*/
private OrderApi order = null;
/**
* 获取 绑定好代理和具体对象后的目标对象的 接口
*
* @param order 具体的订单对象,相当于具体目标对象
* @return 绑定好代理和具体对象后的目标对象的接口
*/
public OrderApi getProxyInterface(Order order) {
// 设置被代理的对象,好方便invoke里面的操作
this.order = order;
// 把真正的订单对象和动态代理关联起来
OrderApi orderApi = (OrderApi) Proxy.newProxyInstance(order.getClass().getClassLoader(), order.getClass().getInterfaces(), this);
return orderApi;
}
/**
* 实现invoke,在这个方法里面,具体判断当前是在调用什么方法,需要如何处理
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// System.out.println("用到的方法有什么"+method.getName());
System.out.println("args有什么"+ Arrays.toString(args));
if (method.getName().startsWith("set")) {
System.out.println("进入setter方法了哟");
// 如果不是创建人,那就不能修改
if (order.getOrderUser() != null && order.getOrderUser().equals(args[1])) {
// 可以操作
return method.invoke(order,args);
}else {
// args[1] 表示第二个才是用户
System.out.println("对不起, " + args[1] + ",您无权修改本订单中的数据");
}
}else if(method.getName().startsWith("to")){
System.out.println("现在调用toString方法了哟");
return method.invoke(order,args);
}else {
// 不是调用setter方法就继续执行
return method.invoke(order,args);
}
return null;
}
}
Client
package day10代理模式;
import day10代理模式.java中的代理类.DynamicProxy;
public class Client {
public static void main(String[] args) {
// 1.张三先创建了一个订单
Order order = new Order("设计模式", 100, "张三");
// 2.创建一个动态代理
DynamicProxy dynamicProxy = new DynamicProxy();
// 3.将订单与动态代理关联起来
OrderApi orderApi = dynamicProxy.getProxyInterface(order);
//4.以下就需要使用被代理过的接口来操作了
//4.1 李四想要来修改,那就会报错
orderApi.setOrderNum(123,"李四");
System.out.println("李四修改后的记录==> "+orderApi);
//4.2 张三修改
orderApi.setOrderNum(123,"张三");
System.out.println("张三修改后的记录==> "+orderApi);
}
}
解析
代理类首先是实现一个名为InvocationHandler的接口。需要持有被代理对象也就是OrderApi,然后通过一个对外提供的方法将代理与被代理绑定起来。实现invoke方法,这个方法就是为了判断订单接口中当前在使用的方法,对正在使用的方法做什么处理
一行一行解析就是首先判断方法名字是不是set开头的,如果是就看一下订单对象是否为空和这个方法传过来的值中的第1个下标对象是不是等于持有的对象,如果是就可以操作,如果不是就提示。
定义
代理模式调用示意图
代理模式的特点
本质
控制对象访问
何时选用