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

代理模式定义如下:

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

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

我们以添加用户业务为例

// 用户接口
package com.ycx.pattern.proxy;
public interface UserService {
public void insertUser();
}
// 用户实现类
package com.ycx.pattern.proxy;
public class UserServiceImpl implements UserService {
@Override
public void insertUser() {
System.out.println("添加用户...");
}
}

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

// 客户端
package com.ycx.pattern.proxy;
public class Client {
public static void main(String[] args) {
UserService userServie = new UserServiceImpl();
userServie.insertUser();
}
}

执行结果
添加用户...

静态代理

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

// 代理
package com.ycx.pattern.proxy;
public class UserServiceProxy implements UserService {
private UserService _userService;
public UserServiceProxy(UserService userService) {
_userService = userService;
}
@Override
public void insertUser() {
// 开始日志
System.out.println("开始");
_userService.insertUser();
// 结束日志
System.out.println("结束");
}
}
// 客户端
package com.ycx.pattern.proxy;
public class Client {
public static void main(String[] args) {
// 创建代理
UserServiceProxy proxy = new UserServiceProxy(new UserServiceImpl());
proxy.insertUser();
}
}

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

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

// 接口
package com.ycx.pattern.proxy;
public interface UserService {
public void insertUser();
public UserService getProxy();
}
// 实现类
package com.ycx.pattern.proxy;
public class UserServiceImpl implements UserService {
private UserServiceProxy proxy = null;
@Override
public void insertUser() {
// 关键代码是判断是不是自己指定的代理
if (!isProxy()) {
System.out.println("请使用指定的代理");
} else {
System.out.println("添加用户...");
}
}
// 关键代码判断代理
private boolean isProxy() {
return this.proxy == null ? false : true;
}
// 关键代码返回自己的代理
@Override
public UserService getProxy() {
this.proxy = new UserServiceProxy(this);
return this.proxy;
}
}
// 代理
package com.ycx.pattern.proxy;
public class UserServiceProxy implements UserService {
private UserService _userService;
public UserServiceProxy(UserService userService) {
_userService = userService;
}
@Override
public void insertUser() {
System.out.println("开始");
_userService.insertUser();
System.out.println("结束");
}
@Override
public UserService getProxy() {
return this;
}
}
// 客户端
package com.ycx.pattern.proxy;
public class Clicent {
public static void main(String[] args) {
// 只有使用自的代理才可以
UserService proxy = new UserServiceImpl().getProxy();
proxy.insertUser();
}
}

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

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

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

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

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

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

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

下面是重头戏

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

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

// 动态代理
package com.ycx.pattern.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object object;
MyInvocationHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始");
Object result = method.invoke(object, args);
System.out.println("结束");
return result;
}
}
// 客户端
package com.ycx.pattern.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
InvocationHandler h = new MyInvocationHandler(new UserServiceImpl());
// 使用Proxy获得实例
UserService proxy = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserService.class}, h);
proxy.insertUser();
}
}

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

// 动态代理
package com.ycx.pattern.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object object;
MyInvocationHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始");
Object result = method.invoke(object, args);
System.out.println("结束");
return result;
}
}
// 客户代理
package com.ycx.pattern.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class DynamicProxy {
@SuppressWarnings("unchecked")
public static <T> T newProxyInstance(T instance) {
ClassLoader loader = instance.getClass().getClassLoader();
Class<?>[] interfaces = instance.getClass().getInterfaces();
InvocationHandler h = new MyInvocationHandler(instance);
return (T) Proxy.newProxyInstance(loader, interfaces, h);
}
}
// 客户端
package com.ycx.pattern.proxy;
public class Client {
public static void main(String[] args) {
// 使用定制的代理返回实例
UserService proxy = DynamicProxy.newProxyInstance(new UserServiceImpl());
proxy.insertUser();
}
}

待续...

【设计模式】代理模式-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. ZeroC ICE源代码中的那些事 - 嵌套类和局部类

    使用嵌套类(类中定义的类,c++没有静态类)或局部类(在函数或成员方法中定义的类),进行行为模式的委托(委托请求)或异步 . java中嵌套类和局部类隐式完成了你对外部对象(实例)访问的私有堆栈的初始 ...

  2. 利用Python学习线性代数 -- 1.1 线性方程组

    利用Python学习线性代数 -- 1.1 线性方程组 本节实现的主要功能函数,在源码文件linear_system中,后续章节将作为基本功能调用. 线性方程 线性方程组由一个或多个线性方程组成,如 ...

  3. LVM弹性硬盘

    LVM机制的基本概念 PV(物理卷) ----由多个pe组成 VG(卷组) LV(逻辑卷) 基本命令: 如: 服务器新增一块大小为1T的SCSI的硬盘(sdb) ,创建一个名字为(ceshi)的逻辑分 ...

  4. 利用tomcat搭建图片服务器

    今天来教大家如何使用 tomcat 来搭建一个图片的服务器 1.先将tomcat解压一份并改名 2.此时apache-tomcat-8.5.43-windows-x64-file为图片服务器 依次打开 ...

  5. Siamese-RPN论文阅读

    https://www.cnblogs.com/zhengyuqian/p/10609737.html

  6. 3sql

    -------------------- 三范式-- 第一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列. -- 第二范式(2NF):首先是 1NF,另外包含两部分内容,一是表必须有一个 ...

  7. ganglia 客户端部署

    #!/bin/bash #配置参数 #serverIP=192.168.1.16 #network=ens32 #关闭selinux #setenforce #sed -i 's/SELINUX=en ...

  8. Git学习笔记01--常用Git命令、cmd命令及Git总结性知识

    资源:外国网友制作的 Git Cheat Sheet 第二次学习廖雪峰老师的Git教程,学习过程中把教程中涉及到的Git命令及总结性知识记录下来方便二次复习. 知识点 所有的版本控制系统,其实只能跟踪 ...

  9. 10-kubernetes serveraccount RBAC

    目录 认证安全 serviceAccountName 和 userAccount serviceaccount 创建 使用admin 的SA 测试 URL访问kubernetes资源 APIserve ...

  10. Centos 6.x Openssh 升级 7.7p1 版本

    OpenSSH 升级 目前在一家金融公司上班,正好赶上金融公司各种暴雷,本人心里慌慌的. 然后就是金融公司要进行的最低的三级等保评测,各种修改系统安全,密码强度.WAF.防火墙等各种. 评测公司对我司 ...