经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
设计模式之代理模式(一)
来源:cnblogs  作者:justBobo  时间:2019/5/27 8:52:15  对本文有异议

一、什么是代理模式

定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

组成:
抽象角色:(主题)通过接口或抽象类声明真实角色实现的业务方法。
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

二、为什么要使用代理模式

意图:为其他对象提供一种代理以控制对这个对象的访问。

主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

应用实例:1、Windows 里面的快捷方式。2、买火车票不一定在火车站买,也可以去代售点。 3、spring aop。

优点: 1、职责清晰。

    被代理对象只负责自己实际的业务逻辑,不关心其他非本身的职责。并将其他事务可以通过代理类处理。

       2、高扩展性。

    无论被代理对象如何改变,只要代理类和被代理类都实现了统一接口,都不同修改代理类,而且即使扩展了新的被代理类,代理类也可以使用,只要创建代理类的时候传入对应的被代理类对象。

 

    3、智能化。

    这主要体现在动态代理中,下面会讲解动态代理。如果有兴趣了解Spring的AOP,其实就是使用了动态代理。

缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。

       2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

注意事项: 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。

         2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。

三、如何用代理模式

  我们举个示例,比如在娱乐圈,客户与艺人进行商业合作,一般都不是与艺人直接联系,签订时间、地点、薪酬等合同,而是

找艺人的经纪人商讨,那么这里商艺活动就是抽象对象(主题),艺人就被代理对象,经纪人就是代理对象。

代码示例:

  1. package com.pattern.proxy;
  2. /**
  3. * 抽象接口 演艺
  4. */
  5. public interface Performance {
  6. public void Sing(String name , String address, String date);//谁在哪个时间哪个地点唱歌
  7.  
  8. public void dance(String name , String address, String date); //谁在哪个时间哪个地点跳舞
  9.  
  10. public void perform(String name , String address, String date);//谁在哪个时间哪个地点表演
  11. }
抽象对象(主题)
  1. package com.pattern.proxy;
  2. /**
  3. * 被代理对象 艺人
  4. */
  5. public class Artist implements Performance{
  6. private Agent agent;// 获取指定代理人对象
  7. //获取指定的代理人对象
  8. public Performance getAgent(){
  9. agent = new Agent(this);
  10. return agent;
  11. }
  12. @Override
  13. public void Sing(String name, String address, String date) {
  14. if (agent == null){
  15. System.out.println("请使用指定的代理类");
  16. }else
  17. System.out.println(date+" "+name +"在"+address +"rap了一首xX");
  18. }
  19. @Override
  20. public void dance(String name, String address, String date) {
  21. if (agent == null){
  22. System.out.println("请使用指定的代理类");
  23. }else
  24. System.out.println( date+" "+name +"在"+address +"跳了一个芭蕾");
  25. }
  26. @Override
  27. public void perform(String name, String address, String date) {
  28. if (agent == null){
  29. System.out.println("请使用指定的代理类");
  30. }else
  31. System.out.println(date+" "+name +"在"+address +"表演了打篮球");
  32. }
  33. }
被代理对象
  1. package com.pattern.proxy;
  2. /**
  3. * 代理对象 经纪人
  4. * Created by wanbf on 2019/5/26.
  5. */
  6. public class Agent implements Performance{
  7. //保存被代理人的实例
  8. private Performance performance;
  9. public Agent(Performance performance){
  10. this.performance = performance;
  11. }
  12. @Override
  13. public void Sing(String name, String address, String date) {
  14. performance.Sing(name,address,date);//这里经纪人是不会唱歌的,执行艺人的唱歌 下同
  15. }
  16. @Override
  17. public void dance(String name, String address, String date) {
  18. performance.dance(name,address,date);
  19. }
  20. @Override
  21. public void perform(String name, String address, String date) {
  22. performance.perform(name,address,date);
  23. }
  24. }
代理对象
  1. public static void main(String[] args){
  2. Performance performance = new Artist().getAgent();
  3. performance.Sing("CXK","韩国", DateFormat.getDateInstance().format(new Date()));
  4. performance.dance("CXK","韩国",DateFormat.getDateInstance().format(new Date()));
  5. performance.perform("CXK","韩国",DateFormat.getDateInstance().format(new Date()));
  6. }
  7. 输出:
  8. 2019-5-26 CXK在韩国rap了一首xX
  9. 2019-5-26 CXK在韩国跳了一个芭蕾
  10. 2019-5-26 CXK在韩国表演了打篮球
测试

上面我们是走指定的代理对象 执行方法;

那么我们不通过代理方法来执行呢,

  1. //不通过代理还执行
  2. Performance performance = new Artist();
  3. performance.Sing("CXK","韩国", DateFormat.getDateInstance().format(new Date()));
  4. performance.dance("CXK","韩国",DateFormat.getDateInstance().format(new Date()));
  5. performance.perform("CXK","韩国",DateFormat.getDateInstance().format(new Date()));
  6. 输出:
  7. 请使用指定的代理类
  8. 请使用指定的代理类
  9. 请使用指定的代理类
不走代理方法

很显然,不用代理方法是不能执行成功的

不是指定代理方法呢,

  1. //不是指定的代理方法
  2. Performance performance = new Agent(new Artist());
  3. performance.Sing("CXK","韩国", DateFormat.getDateInstance().format(new Date()));
  4. performance.dance("CXK","韩国",DateFormat.getDateInstance().format(new Date()));
  5. performance.perform("CXK","韩国",DateFormat.getDateInstance().format(new Date()));
  6. 输出:
  7. 请使用指定的代理类
  8. 请使用指定的代理类
  9. 请使用指定的代理类
不是指定的代理方法

显然不是指定的代理方法也是执行不了的

 这个示例是强制代理模式,概念就是要从真是角色那里查找到代理角色,不允许直接访问真实角色。

上层模块只需要调用Agent()获取代理来访问真实角色的所有方法,它根本就不需要产生一个代理角色,代理的管理已经由真实角色自己来完成。

后续讲解一个 基本代理 、普通代理、虚拟代理模式 和动态代理模式。

原文链接:http://www.cnblogs.com/justBobo/p/10927408.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号