转载:https://www.cnblogs.com/yangchongxing/p/7654725.html

代理模式定义如下:

Provide a surrogate or placeholder for another object to control access to it。为另一个对象提供一个代理或占位符以控制对它的访问。

代理模式使用非常广泛,理解代理模式对解决实际问题大有裨益的。使用代理模式必须让代理类和目标类实现相同的接口。

我们以添加用户业务为例

  1. // 用户接口
  2. package com.ycx.pattern.proxy;
  3. public interface UserService {
  4. public void insertUser();
  5. }
  6. // 用户实现类
  7. package com.ycx.pattern.proxy;
  8. public class UserServiceImpl implements UserService {
  9. @Override
  10. public void insertUser() {
  11. System.out.println("添加用户...");
  12. }
  13. }

我们若要添加一个用户信息,需要new一个UserServiceImpl实例对象,然后调用insertUser方法。代码如下:

  1. // 客户端
  2. package com.ycx.pattern.proxy;
  3. public class Client {
  4. public static void main(String[] args) {
  5. UserService userServie = new UserServiceImpl();
  6. userServie.insertUser();
  7. }
  8. }

执行结果
添加用户...

静态代理

若这时新添一个业务,添加用户要在insertUser方法的开始和结束追加日志,其他地方没有这个业务,所以添加用户的业务不能修改,这种情况可以使用代理实现。代码如下:

  1. // 代理
  2. package com.ycx.pattern.proxy;
  3. public class UserServiceProxy implements UserService {
  4. private UserService _userService;
  5. public UserServiceProxy(UserService userService) {
  6. _userService = userService;
  7. }
  8. @Override
  9. public void insertUser() {
  10. // 开始日志
  11. System.out.println("开始");
  12. _userService.insertUser();
  13. // 结束日志
  14. System.out.println("结束");
  15. }
  16. }
  17. // 客户端
  18. package com.ycx.pattern.proxy;
  19. public class Client {
  20. public static void main(String[] args) {
  21. // 创建代理
  22. UserServiceProxy proxy = new UserServiceProxy(new UserServiceImpl());
  23. proxy.insertUser();
  24. }
  25. }

执行结果
开始
添加用户...
结束

上边的代理是比较随便的,只要实现了用户接口,都可以,再看看使用指定代理,这样代理就必须是制定的。代码如下:

  1. // 接口
  2. package com.ycx.pattern.proxy;
  3. public interface UserService {
  4. public void insertUser();
  5. public UserService getProxy();
  6. }
  7. // 实现类
  8. package com.ycx.pattern.proxy;
  9. public class UserServiceImpl implements UserService {
  10. private UserServiceProxy proxy = null;
  11. @Override
  12. public void insertUser() {
  13. // 关键代码是判断是不是自己指定的代理
  14. if (!isProxy()) {
  15. System.out.println("请使用指定的代理");
  16. } else {
  17. System.out.println("添加用户...");
  18. }
  19. }
  20. // 关键代码判断代理
  21. private boolean isProxy() {
  22. return this.proxy == null ? false : true;
  23. }
  24. // 关键代码返回自己的代理
  25. @Override
  26. public UserService getProxy() {
  27. this.proxy = new UserServiceProxy(this);
  28. return this.proxy;
  29. }
  30. }
  31. // 代理
  32. package com.ycx.pattern.proxy;
  33. public class UserServiceProxy implements UserService {
  34. private UserService _userService;
  35. public UserServiceProxy(UserService userService) {
  36. _userService = userService;
  37. }
  38. @Override
  39. public void insertUser() {
  40. System.out.println("开始");
  41. _userService.insertUser();
  42. System.out.println("结束");
  43. }
  44. @Override
  45. public UserService getProxy() {
  46. return this;
  47. }
  48. }
  49. // 客户端
  50. package com.ycx.pattern.proxy;
  51. public class Clicent {
  52. public static void main(String[] args) {
  53. // 只有使用自的代理才可以
  54. UserService proxy = new UserServiceImpl().getProxy();
  55. proxy.insertUser();
  56. }
  57. }

执行结果
开始
添加用户...
结束

我们来直接new一个对象执行,或者new一个代理,验证结果。代码如下:

  1. // 客户端
  2. package com.ycx.pattern.proxy;
  3. public class Client {
  4. public static void main(String[] args) {
  5. // 直接new一个对象
  6. new UserServiceImpl().insertUser();
  7. }
  8. }

执行结果
请使用制定的代理

  1. // 客户端
  2. package com.ycx.pattern.proxy;
  3. public class Client {
  4. public static void main(String[] args) {
  5. // 直接new一个代理
  6. UserServiceProxy proxy = new UserServiceProxy(new UserServiceImpl());
  7. proxy.insertUser();
  8. }
  9. }

执行结果
开始
请使用制定的代理
结束

从上面看都是不行的,只能使用指定的代理才可以。

下面是重头戏

动态代理-即面向横切面编程AOP(Aspect Oriented Programming)
InvocationHandler 是JDK提供的动态代理接口。Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

还是上面的例子,用动态代理实现代码如下:

  1. // 动态代理
  2. package com.ycx.pattern.proxy;
  3. import java.lang.reflect.InvocationHandler;
  4. import java.lang.reflect.Method;
  5. public class MyInvocationHandler implements InvocationHandler {
  6. private Object object;
  7. MyInvocationHandler(Object object) {
  8. this.object = object;
  9. }
  10. @Override
  11. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  12. System.out.println("开始");
  13. Object result = method.invoke(object, args);
  14. System.out.println("结束");
  15. return result;
  16. }
  17. }
  18. // 客户端
  19. package com.ycx.pattern.proxy;
  20. import java.lang.reflect.InvocationHandler;
  21. import java.lang.reflect.Proxy;
  22. public class Client {
  23. public static void main(String[] args) {
  24. InvocationHandler h = new MyInvocationHandler(new UserServiceImpl());
  25. // 使用Proxy获得实例
  26. UserService proxy = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserService.class}, h);
  27. proxy.insertUser();
  28. }
  29. }

上面的实现方式客户端使用起来不方便,可以定义一个专门的客户代理。代码如下:

  1. // 动态代理
  2. package com.ycx.pattern.proxy;
  3. import java.lang.reflect.InvocationHandler;
  4. import java.lang.reflect.Method;
  5. public class MyInvocationHandler implements InvocationHandler {
  6. private Object object;
  7. MyInvocationHandler(Object object) {
  8. this.object = object;
  9. }
  10. @Override
  11. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  12. System.out.println("开始");
  13. Object result = method.invoke(object, args);
  14. System.out.println("结束");
  15. return result;
  16. }
  17. }
  18. // 客户代理
  19. package com.ycx.pattern.proxy;
  20. import java.lang.reflect.InvocationHandler;
  21. import java.lang.reflect.Proxy;
  22. public class DynamicProxy {
  23. @SuppressWarnings("unchecked")
  24. public static <T> T newProxyInstance(T instance) {
  25. ClassLoader loader = instance.getClass().getClassLoader();
  26. Class<?>[] interfaces = instance.getClass().getInterfaces();
  27. InvocationHandler h = new MyInvocationHandler(instance);
  28. return (T) Proxy.newProxyInstance(loader, interfaces, h);
  29. }
  30. }
  31. // 客户端
  32. package com.ycx.pattern.proxy;
  33. public class Client {
  34. public static void main(String[] args) {
  35. // 使用定制的代理返回实例
  36. UserService proxy = DynamicProxy.newProxyInstance(new UserServiceImpl());
  37. proxy.insertUser();
  38. }
  39. }

待续...

【设计模式】代理模式-Proxy的更多相关文章

  1. 设计模式——代理模式(Proxy Pattern)

    代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. UML图: 模型设计: Subject类: package com.cnblog.clarck; /** * Subject 类 ...

  2. 设计模式 - 代理模式(proxy pattern) 未使用代理模式 具体解释

    代理模式(proxy pattern) 未使用代理模式 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 部分代码參考: http://blog.csdn. ...

  3. 设计模式--代理模式Proxy(结构型)

    一.代理模式 为其他对象提供一种代理以控制对这个对象的访问. 代理模式分为四种: 远程代理:为了一个对象在不同的地址空间提供局部代表.这样可以隐藏一个对象存在于不同地址空间的事实. 虚拟代理:根据需要 ...

  4. C#设计模式——代理模式(Proxy Pattern)

    一.概述在软件开发中,有些对象由于创建成本高.访问时需要与其它进程交互等原因,直接访问会造成系统速度慢.复杂度增大等问题.这时可以使用代理模式,给系统增加一层间接层,通过间接层访问对象,从而达到隐藏系 ...

  5. 设计模式-代理模式(Proxy)

    应用场景: 领导都有秘书,一般会代理领导的部分职能角色,处理签字.报销.开会等任务.很多新人可能都只知道秘书的存在,毕竟每天与其打交道,不知道领导的存在.但是领导的的确确是真实存在的. 场景说明: 代 ...

  6. 大话设计模式--代理模式 proxy

    1. 代理模式: 为其他对象提供一种代理以控制这个对象的访问. 代理模式使用场合: a. 远程代理, 为一个对象在不同的地址空间提供局部代理,隐藏一个对象存在于不同地址空间的事实.如.net中WebS ...

  7. 23种设计模式--代理模式-Proxy

    一.代理模式的介绍       代理模式我们脑袋里出现第一个词语就是代购,其实就是这样通过一个中间层这个中间成是属于什么都干什么都买得,俗称"百晓生",在平时得开发中我们经常会听到 ...

  8. 设计模式 -- 代理模式 (Proxy Pattern)

    定义: 为其他对象提供一种代理以控制对这个对象的访问: 角色: 1,抽象主题类,(接口或者抽象类),抽象真实主题和代理的共有方法(如下Subject类): 2,具体实现的主题类,继承或者实现抽象主题类 ...

  9. 深入浅出设计模式——代理模式(Proxy Pattern)

    模式动机在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现间接引用.代理对象可以在客户端和目标对象之间起到中介的作用,并且可以通过代理对象去掉客户不能看到 ...

  10. 【转】设计模式(十一)代理模式Proxy(结构型)

    设计模式(十一)代理模式Proxy(结构型) 1.概述 因为某个对象消耗太多资源,而且你的代码并不是每个逻辑路径都需要此对象, 你曾有过延迟创建对象的想法吗 ( if和else就是不同的两条逻辑路径) ...

随机推荐

  1. Spring Boot: Spring Doc生成OpenAPI3.0文档

    1. 概述 公司正好最近在整理项目的文档,且文档对于构建REST API来说是至关重要的.在这篇文章中,我将介绍Spring Doc , 一个基于OpenAPI 3规范简化了Spring Boot 1 ...

  2. Docker从入门到实践(4-1)

    使用 Docker 镜像 在之前的介绍中,我们知道镜像是 Docker 的三大组件之一. Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像. ...

  3. 红帽学习记录[RHCE] 防火墙与网络合作

    目录 防火墙 基本介绍 firewalld 区域zone 管理firewalld 关于富规则 定义 firewalld操作富规则的命令 语法 常用的示例 网络合作 链路聚合 网络组的文件 网络组命令 ...

  4. Java基础知识总结之1.8新特性lambda表达式

    函数式接口 函数式接口(functional interface 也叫功能性接口,其实是同一个东西).简单来说,函数式接口是只包含一个方法的接口.比如Java标准库中的java.lang.Runnab ...

  5. .NET Core 3.0 使用Nswag生成Api文档和客户端代码

    摘要 在前后端分离.Restful API盛行的年代,完美的接口文档,成了交流的纽带.在项目中引入Swagger (也称为OpenAPI),是种不错的选择,它可以让接口数据可视化.下文将会演示 利用N ...

  6. Jenkins 实现前端自动打包,自动部署代码及邮件提醒功能

    在之前的公司,我们前端使用webpack构建项目,项目构建完成后,我们会使用ftp或linux的一些命令工具上传我们的文件到服务器上,这种方式虽然是可以,但是最近面试的时候,人家会问我前端如何部署项目 ...

  7. Fortran文件读写--查找内容

    program ex implicit none character(len=) A(),B(),C() !A异常.B已开挖.C需标记 integer i,j,N1,N2,count !N1是10号文 ...

  8. 【python测试开发栈】—python内存管理机制(二)—垃圾回收

    在上一篇文章中(python 内存管理机制-引用计数)中,我们介绍了python内存管理机制中的引用计数,python正是通过它来有效的管理内存.今天来介绍python的垃圾回收,其主要策略是引用计数 ...

  9. Django简介以及MVC模式

    一.简介 Django,是当前Python世界里最负盛名且成熟的网络框架.最初用来制作在线新闻的Web站点. Django是一个基于python的web重量级框架 重指的是为发开者考虑的多 采用了MV ...

  10. telnet指令研究—以网络聊天程序为例

    一.telnet指令 Telnet取名自Telecommunications和Networks的联合缩写,是早期个人计算机上连接到服务器主机的一个网络指令,由于存在安全问题,现在已经很少被使用.在wi ...