设计模式之代理模式(一)
一、什么是代理模式
定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
二、为什么要使用代理模式
意图:为其他对象提供一种代理以控制对这个对象的访问。
主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
应用实例:1、windows 里面的快捷方式。2、买火车票不一定在火车站买,也可以去代售点。 3、spring aop。
优点: 1、职责清晰。
被代理对象只负责自己实际的业务逻辑,不关心其他非本身的职责。并将其他事务可以通过代理类处理。
2、高扩展性。
无论被代理对象如何改变,只要代理类和被代理类都实现了统一接口,都不同修改代理类,而且即使扩展了新的被代理类,代理类也可以使用,只要创建代理类的时候传入对应的被代理类对象。
3、智能化。
这主要体现在动态代理中,下面会讲解动态代理。如果有兴趣了解spring的aop,其实就是使用了动态代理。
缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
注意事项: 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
三、如何用代理模式
我们举个示例,比如在娱乐圈,客户与艺人进行商业合作,一般都不是与艺人直接联系,签订时间、地点、薪酬等合同,而是
找艺人的经纪人商讨,那么这里商艺活动就是抽象对象(主题),艺人就被代理对象,经纪人就是代理对象。
代码示例:
package com.pattern.proxy; /** * 抽象接口 演艺 */ public interface performance { public void sing(string name , string address, string date);//谁在哪个时间哪个地点唱歌 public void dance(string name , string address, string date); //谁在哪个时间哪个地点跳舞 public void perform(string name , string address, string date);//谁在哪个时间哪个地点表演 }
package com.pattern.proxy; /** * 被代理对象 艺人 */ public class artist implements performance{ private agent agent;// 获取指定代理人对象 //获取指定的代理人对象 public performance getagent(){ agent = new agent(this); return agent; } @override public void sing(string name, string address, string date) { if (agent == null){ system.out.println("请使用指定的代理类"); }else system.out.println(date+" "+name +"在"+address +"rap了一首xx"); } @override public void dance(string name, string address, string date) { if (agent == null){ system.out.println("请使用指定的代理类"); }else system.out.println( date+" "+name +"在"+address +"跳了一个芭蕾"); } @override public void perform(string name, string address, string date) { if (agent == null){ system.out.println("请使用指定的代理类"); }else system.out.println(date+" "+name +"在"+address +"表演了打篮球"); } }
package com.pattern.proxy; /** * 代理对象 经纪人 * created by wanbf on 2019/5/26. */ public class agent implements performance{ //保存被代理人的实例 private performance performance; public agent(performance performance){ this.performance = performance; } @override public void sing(string name, string address, string date) { performance.sing(name,address,date);//这里经纪人是不会唱歌的,执行艺人的唱歌 下同 } @override public void dance(string name, string address, string date) { performance.dance(name,address,date); } @override public void perform(string name, string address, string date) { performance.perform(name,address,date); } }
public static void main(string[] args){ performance performance = new artist().getagent(); performance.sing("cxk","韩国", dateformat.getdateinstance().format(new date())); performance.dance("cxk","韩国",dateformat.getdateinstance().format(new date())); performance.perform("cxk","韩国",dateformat.getdateinstance().format(new date())); } 输出: 2019-5-26 cxk在韩国rap了一首xx 2019-5-26 cxk在韩国跳了一个芭蕾 2019-5-26 cxk在韩国表演了打篮球
上面我们是走指定的代理对象 执行方法;
那么我们不通过代理方法来执行呢,
//不通过代理还执行 performance performance = new artist(); performance.sing("cxk","韩国", dateformat.getdateinstance().format(new date())); performance.dance("cxk","韩国",dateformat.getdateinstance().format(new date())); performance.perform("cxk","韩国",dateformat.getdateinstance().format(new date())); 输出: 请使用指定的代理类 请使用指定的代理类 请使用指定的代理类
很显然,不用代理方法是不能执行成功的
不是指定代理方法呢,
//不是指定的代理方法 performance performance = new agent(new artist()); performance.sing("cxk","韩国", dateformat.getdateinstance().format(new date())); performance.dance("cxk","韩国",dateformat.getdateinstance().format(new date())); performance.perform("cxk","韩国",dateformat.getdateinstance().format(new date())); 输出: 请使用指定的代理类 请使用指定的代理类 请使用指定的代理类
显然不是指定的代理方法也是执行不了的
这个示例是强制代理模式,概念就是要从真是角色那里查找到代理角色,不允许直接访问真实角色。
上层模块只需要调用agent()获取代理来访问真实角色的所有方法,它根本就不需要产生一个代理角色,代理的管理已经由真实角色自己来完成。
后续讲解一个 基本代理 、普通代理、虚拟代理模式 和动态代理模式。
下一篇: 怎么着也得给你咬个怀表