11.3.5 思考代理模式
1:代理模式的本质
代理模式的本质:控制对象访问。
代理模式通过代理目标对象,把代理对象插入到客户和目标对象之间,从而为客户和目标对象引入一定的间接性,正是这个间接性,给了代理对象很多的活动空间,代理对象可以在调用具体的目标对象前后,附加很多操作,从而实现新的功能或是扩展目标对象的功能,更狠的是,代理对象还可以不去创建和调用目标对象,也就是说,目标对象被完全代理掉了,或是被替换掉了。
从实现上看,代理模式主要是使用对象的组合和委托,尤其是在静态代理的实现里面,会看得更清楚。但是也可以采用对象继承的方式来实现代理,这种实现方式在某些情况下,比使用对象组合还要来得简单。
举个例子来说明一下,改造11.3.2保护代理的例子来说明。
(1)首先就是去掉OrderApi,现在改成继承的方式实现代理,不再需要公共的接口了
(2)Order对象变化不大,只是去掉实现的OrderApi接口就好了,示例代码如下:
| public class Order //其它的代码没有任何变化,就不去赘述了 } |
(3)再看看代理的实现,变化较多,大致有如下的变化:
- 不再实现OrderApi,而改成继承Order
- 不需要再持有目标对象了,因为这个时候父类就是被代理的对象
- 原来的构造方法去掉,重新实现一个传入父类需要的数据的构造方法
- 原来转调目标对象的方法,现在变成调用父类的方法了,用super关键字
- 除了几个被保护代理的setter方法外,不再需要getter方法了
示例代码如下:
/**
* 订单的代理对象
*/
public class OrderProxy extends Order{
public OrderProxy(String productName
,int orderNum,String orderUser){
super(productName,orderNum,orderUser);
}
public void setProductName(String productName,String user) {
//控制访问权限,只有创建订单的人员才能够修改
if(user!=null && user.equals(this.getOrderUser())){
super.setProductName(productName, user);
}else{
System.out.println("对不起"+user
+",您无权修改订单中的产品名称。");
}
}
public void setOrderNum(int orderNum,String user) {
//控制访问权限,只有创建订单的人员才能够修改
if(user!=null && user.equals(this.getOrderUser())){
super.setOrderNum(orderNum, user);
}else{
System.out.println("对不起"+user
+",您无权修改订单中的订购数量。");
}
}
public void setOrderUser(String orderUser,String user) {
//控制访问权限,只有创建订单的人员才能够修改
if(user!=null && user.equals(this.getOrderUser())){
super.setOrderUser(orderUser, user);
}else{
System.out.println("对不起"+user
+",您无权修改订单中的订购人。");
}
}
public String toString(){
return "productName="+this.getProductName()+",orderNum="
+this.getOrderNum()+",orderUser="+this.getOrderUser();
}
}
(4)客户端的变化不大,主要是不再直接面向OrderApi接口,而是使用Order对象了,另外创建代理的构造方法也发生了变化,示例代码如下:
public class Client {
public static void main(String[] args) {
//张三先登录系统创建了一个订单
Order order = new OrderProxy("设计模式",100,"张三");
//李四想要来修改,那就会报错
order.setOrderNum(123, "李四");
//输出order
System.out.println("李四修改后订单记录没有变化:"+order);
//张三修改就不会有问题
order.setOrderNum(123, "张三");
//再次输出order
System.out.println("张三修改后,订单记录:"+order);
}
}
去运行一下,测试看看,体会一下这种实现方式。
2:何时选用代理模式
建议在如下情况中,选用代理模式:
- 需要为一个对象在不同的地址空间提供局部代表的时候,可以使用远程代理
- 需要按照需要创建开销很大的对象的时候,可以使用虚代理
- 需要控制对原始对象的访问的时候,可以使用保护代理
- 需要在访问对象的时候执行一些附加操作的时候,可以使用智能指引代理
11.3.6 相关模式
l 代理模式和适配器模式
这两个模式有一定的相似性,但也有差异。
这两个模式有相似性,它们都为另一个对象提供间接性的访问,而且都是从自身以外的一个接口向这个对象转发请求。
但是从功能上,两个模式是不一样的。适配器模式主要用来解决接口之间不匹配的问题,它通常是为所适配的对象提供一个不同的接口;而代理模式会实现和目标对象相同的接口。l 代理模式和装饰模式
这两个模式从实现上相似,但是功能上是不同的。
装饰模式的实现和保护代理的实现上是类似的,都是在转调其它对象的前后执行一定的功能。但是它们的目的和功能都是不同的。
装饰模式的目的是为了让你不生成子类就可以给对象添加职责,也就是为了动态的增加功能;而代理模式的主要目的是控制对对象的访问。更多设计课程搜索“跟着CC学设计”即可