note:今天学习代理模式,以前在学习hibernate的时候就看到了代理模式的运用情节了的,一直没有去研究过呃
一、代理模式的定义?
为其它对象提供一种代理以控制对这个对象的访问。
二、代理模式的功能?
代理模式是通过创建一个代理对象,用这个代理对象去代表真的对象,客户端得到这个代理对象后,对客户端并没有什么影响,就跟得到真的对象是一样的。当客户端操作这个对象时,实际上的功能还是真实的对象去完成的。只是通过代理对象,代理操作真正的对象。正是因为有代理对象夹在客户端和真实对象之间,就相当于一个中转,在中转的时候,我们就可以做点自己想干的事了。比如,判断一下权限,若果没有足够的权限,就不去中转了。
三、代理模式的本质?
代理模式的本质主要是去控制对象的访问,主要使用对象的组合和委托。
四、代理模式的分类?
虚代理:根据需要来创建开销很大的对象,该对象只有在需要的时候才会被真正创建。
远程代理:用来在不同的地址空间上代表同一个对象,这个不同的地址空间可以在本机,也可以在其他机器上。在java里面最经典的就是RMI技术。
copy-on-write:在客户端操作的时候,只有该对象确实改变了,才会真正的copy一个目标对象。
保护代理:控制对原始对象的访问,如果有需要,可以给不同的用户不同的权限,以控制他们对原始对象的访问。
Cache代理:为哪些昂贵的操作提供临时的存储空间,以便多个客户端可以共享这些结果。
防火墙代理:保护对象不被恶意用户访问或者操作。
同步代理:使多个用户能够同时访问目标,对象而没有冲突。
智能引导:在访问对象,执行一些附加操作。
。。。
五、代理模式的角色:
1)抽象角色: 声明真实对象和抽象对象的公共接口。
2)代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
3)真实角色:即我们实际上需要操作的对象。
六、代理模式简答案列:
(个人是觉得比较经典的案例,用户修改权限管理)
1)OrderApi 抽象角色一个公共接口
package com.ly.testproxy.main;
public interface OrderApi {
/**
* 获取产品名称
* @return String
*/
public String getProductName();
/**
* 设置产品名称
* @param productName
* @param user 做权限判断
*/
public void setProductName(String productName,String user);
/**
* 获取订单编号
* @return
*/
public int getOrderNum();
/**
* 设置订单编号
* @param orderNum
* @param user 做权限判断
*/
public void setOrderNum(int orderNum,String user);
/**
* 获取订单用户
* @return
*/
public String getOrderUser();
/**
* 设置账单用户
* @param orderUser
* @param user
*/
public void setOrderUser(String orderUser,String user);
}
2)Order真实的角色,真正执行功能的角色
package com.ly.testproxy.main;
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;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName,String user) {
this.productName = productName;
}
public int getOrderNum() {
return orderNum;
}
public void setOrderNum(int orderNum,String user) {
this.orderNum = orderNum;
}
public String getOrderUser() {
return orderUser;
}
public void setOrderUser(String orderUser,String user) {
this.orderUser = orderUser;
}
}
3)OrderProxy代理类
package com.ly.testproxy.main;
public class OrderProxy implements OrderApi {
private Order order = null;
public OrderProxy(Order realSubject){
this.order = realSubject;
}
@Override
public String getProductName() {
// TODO Auto-generated method stub
return this.order.getProductName();
}
@Override
public void setProductName(String productName, String user) {
//控制访问权限,只有创建订单的人员才能修改
if(user!=null&&user.equals(this.getOrderUser())){
order.setProductName(productName, user);
}else{
System.out.println("对不起"+user+",你无权修改订单中的产品名称!");
}
}
@Override
public int getOrderNum() {
// TODO Auto-generated method stub
return this.order.getOrderNum();
}
@Override
public void setOrderNum(int orderNum,String user) {
//控制访问权限,只有创建订单的人员才能修改
if(user!=null&&user.equals(this.getOrderUser())){
order.setOrderNum(orderNum, user);
}else{
System.out.println("对不起"+user+",你无权修改订单中的产品名称!");
}
}
@Override
public String getOrderUser() {
// TODO Auto-generated method stub
return this.order.getOrderUser();
}
@Override
public void setOrderUser(String orderUser, String user) {
// TODO Auto-generated method stub
//控制访问权限,只有创建订单的人员才能修改
if(user!=null&&user.equals(this.getOrderUser())){
order.setOrderUser(orderUser, user);
}else{
System.out.println("对不起"+user+",你无权修改订单中的产品名称!");
}
}
}
4)Client测试客户端
package com.ly.testproxy.main;
public class Client {
public static void main(String[] args) {
//张三先登录系统创建一个订单
OrderApi order = new OrderProxy(new Order("代理模式",1000, "张三"));
//李四想要来修改,那就会报错
order.setOrderNum(123, "李四");
System.out.println("李四修改后订单没变化"+order.getOrderNum());
//张三就可以修改的
order.setOrderNum(231, "张三");
System.out.println("张三修改后订单"+order.getOrderNum());
}
}
输出结果:
对不起李四,你无权修改订单中的产品名称!
李四修改后订单变化1000
张三修改后订单231
5)总结:从上面的案例,我们可以清楚的理解代理模式的作用和简单写法,即使用真实类之前,我们使用代理类,可以执行一些我们想做的其它操作,比如这里的权限验证,保护了真实对象的方法,只有拥有权限的人才可以操作。
七、Java中的代理模式(动态代理和静态代理):
静态代理:自己定义的代理模式;
动态代理:使用java内建的对代理模式支持的功能实现的代理模式;
使用java动态代理改变上面案例为:(公共接口不变,只改变代理类)
package com.ly.testproxy.main;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxy implements InvocationHandler {
/**
* 被代理的对象
*/
private OrderApi order = null;
public OrderApi getProxyInterface(Order order){
this.order = order;
OrderApi orderApi = (OrderApi) Proxy.newProxyInstance(order.getClass().getClassLoader(),
order.getClass().getInterfaces(),
this);
return orderApi;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().startsWith("set")){
if(order.getOrderUser()!=null&&order.getOrderUser().equals(args[1])){
//
return method.invoke(order, args);
}else{
System.out.println("用户"+args[1]+".你没有修改该信息的权限!");
}
}else{
return method.invoke(order, args);
}
return null;
}
}
然后新的客户端代码变成:
package com.ly.testproxy.main;
public class Client {
public static void main(String[] args) {
// OrderApi order = new OrderProxy(new Order("",1000, "张三"));
// 李四想要修改数据
// order.setOrderNum(123, "李四");
// System.out.println("修改后的数据"+order.getOrderNum());
// 张三修改数据
// order.setOrderNum(231, "张三");
// System.out.println("修改后的数据。"+order.getOrderNum());
Order order = new Order("设计模式", 100, "张三");
DynamicProxy dynamicProxy = new DynamicProxy();
OrderApi orderApi = dynamicProxy.getProxyInterface(order);
orderApi.setOrderNum(123, "李四");
System.out.println("李四修改后订单记录没变化" + order.getOrderNum());
orderApi.setOrderNum(123, "张三");
System.out.println("张三修改后,记录为:" + order.getOrderNum());
}
}
运行后的结果为:
用户李四.你没有修改该信息的权限!
李四修改后订单记录没变化100
张三修改后,记录为:123
效果是一样的。
代理模式就到这了吧,额还是说说两个和代理模式具有相似性的模式的区别吧
1)代理模式和适配器模式:
其实我们只需要明白,代理模式的核心,主要就是控制对象访问,那区别就简单了,适配器模式是干嘛的?主要用来解决接口与接口之间不匹配为的,它通常是为所适配的对象提供一个不同的接口;而代理模式会实现和目标对象相同的接口。
2)代理模式和装饰模式:
这个更好区分了吧,装饰模式的核心,主要是为了让你再不生成子类就可以给对象动态添加职责或则说是功能;而代理模式的核心是控制对象的访问。