Proxyr设计模式之代理模式
Demo地址
https://github.com/rocky123shine/ProxyDemo
概念
Proxy模式,也称代理模式,其定义是为其他对象提供一种代理以控制对这个对象的访问,简单的说就是在访问和被访问对象中间加上的一个间接层,以隔离访问者和被访问者的实现细节。
代理的作用
为其他对象提供一种代理,控制这个对象的访问
代理的分类
虚代理( Remote Proxy )
代理一些开销很大的对象,这样便能迅速返回,进行其它操作,只有在真正需要时才实例化
远程代理( Remote Proxy )
为一个对象在不同的地址空间提供局部代表。
保护代理(Protection Proxy)
控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。
智能指引(Smart Reference)
他取代了简单的指针,它在访问对象时执行一些附加操作。
对应代理使用的场景
当客户端对象需要访问远程主机中的对象时可以使用远程代理。
当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时可以使用虚拟代理,例如一个对象需要很长时间才能完成加载时。
当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时可以使用缓冲代理。
通过使用缓冲代理,系统无须在客户端每一次访问时都重新执行操作,只需直接从临时缓冲区获取操作结果即可。
当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时可以使用保护代理。
当需要为一个对象的访问(引用)提供一些额外的操作时可以使用智能引用代理。
代理模式角色
抽象对象(目标接口)
声明了目标对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象。
目标对象
定义了代理对象所代表的目标对象。
代理对象
代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象;代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象。 代理对象通常在客户端调用传递给目标对象之前或之后,执行某个操作,而不是单纯地将调用传递给目标对象。
代理对象的特点:
1. 实现目标接口(可有可无,标准有)
2. 持有目标对象引用
代理模式分类
静态代理
代理类有程序员生成的为静态代理
动态代理
代理类有系统生成的为动态代理(在运行时刻动态生成代理类)
静态代理简单举例
案例情景:买一部最新苹果手机,大陆买不到,需要在台湾找人代理购买
目标接口
//目标接口
public interface IShopPhone {
//买手机
void shopPhone(String phoneName);
}
目标对象
//目标对象 目标对象实现目标接口
public class SunnyShopPhone implements IShopPhone {
@Override
public void shopPhone(String phoneName) {
System.out.println("手机名称:" + phoneName);
}
}
代理对象
//代理对象 此处为标准代理模式 实现了目标接口(变种可不实现)
public class ProxyShopPhone implements IShopPhone {
private IShopPhone shopPhone;
public ProxyShopPhone(IShopPhone shopPhone){
this.shopPhone = shopPhone;
}
//代理对象实现购买的动作
@Override
public void shopPhone(String phoneName) {
this.shopPhone.shopPhone(phoneName);
}
}
使用:
IShopPhone phone = new SunnyShopPhone();
IShopPhone proxy = new ProxyShopPhone(phone);
proxy.shopPhone("iPhoneX");//购买IphoneX
动态代理简单举例
案例情景:商家工作人员查询订单信息,不同人员权限不同,有的可以修改价格,有的不可以
目标接口
//目标接口
public interface IOrder {
public String getOrderId();
public void setOrderId(String orderId);
public String getOrderName();
public void setOrderName(String orderName);
public String getOrderPrice();
public void setOrderPrice(String orderPrice);
public String getOrderUserName();
public void setOrderUserName(String orderUserName);
}
目标对象
//目标对象 实现目标接口
public class OrderBean implements IOrder {
private String orderId;
private String orderName;
private String orderPrice;
private String orderUserName;
public OrderBean() {
}
public OrderBean(String orderId, String orderName, String orderPrice,
String orderUserName) {
super();
this.orderId = orderId;
this.orderName = orderName;
this.orderPrice = orderPrice;
this.orderUserName = orderUserName;
}
@Override
public String getOrderId() {
return orderId;
}
@Override
public void setOrderId(String orderId) {
this.orderId = orderId;
}
@Override
public String getOrderName() {
return orderName;
}
@Override
public void setOrderName(String orderName) {
this.orderName = orderName;
}
@Override
public String getOrderPrice() {
return orderPrice;
}
@Override
public void setOrderPrice(String orderPrice) {
this.orderPrice = orderPrice;
}
@Override
public String getOrderUserName() {
return orderUserName;
}
@Override
public void setOrderUserName(String orderUserName) {
this.orderUserName = orderUserName;
}
@Override
public String toString() {
return "OrderBean [orderId=" + orderId + ", orderName=" + orderName
+ ", orderPrice=" + orderPrice + ", orderUserName="
+ orderUserName + "]";
}
}
反射获取目标接口
Class<?>[] interfaces = orderBean.getClass().getInterfaces();
生成代理对象
//参数1 目标对象类,
//参数2 目标接口
//参数3 InvocationHandler 对象
IOrder proxyOrder = (IOrder) Proxy.newProxyInstance(orderBean.getClass().getClassLoader(), interfaces,newOrderInvocationHandler(orderBean));
自定义 InvocationHandler(动态代理中的重点)
public class OrderInvocationHandler implements InvocationHandler {
private IOrder order;
public OrderInvocationHandler(IOrder order){
this.order = order;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//反射机制处理->(动态访问属性和方法)
if("getOrderPrice".equals(method.getName())){
//权限处理
if (!"AAAA".equals(this.order.getOrderUserName())){
try {
throw new SecurityException("没有权限访问,请确定你是否是管理员用户...");
} catch (Exception e) {
e.printStackTrace();
}
} else {
String price = OrderService.queryPrice(order.getOrderId());
order.setOrderPrice(price);
}
}
return method.invoke(order, args);
}
}
使用:
// 首先查询所有数据
List<OrderBean> orderList = OrderService.getOrderList();
// 目标对象
OrderBean orderBean = orderList.get(0);
// 目标接口
Class<?>[] interfaces = orderBean.getClass().getInterfaces();
// 代理对象
//OrderInvocationHandler作用:监听proxyOrder方法调用
IOrder proxyOrder = (IOrder) Proxy.newProxyInstance(orderBean
.getClass().getClassLoader(), interfaces,
new OrderInvocationHandler(orderBean));
System.out.println("订单ID: " + proxyOrder.getOrderId());
System.out.println("订单名称: " + proxyOrder.getOrderName());
System.out.println("订单用户名: " + proxyOrder.getOrderUserName());
System.out.println("订单价格: " + proxyOrder.getOrderPrice());