1.什么是代理设计模式

所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象。

这里举一个栗子:就拿我们平时租房子来举例子,好比租客和房主之间的关系,我们租房子往往不会挨个去找房东,而是通过中间的代理者,也就是中介完成,租客来间接的和房主接触,这个时候租客(Tenant)相当于用户中介(AgencyProxy)相当于代理者房主(Homeowner)相当于被代理者。

在代理模式中还分为两种模式:静态代理和动态代理,下面我们通过代码来演示以下两种代理方式。

2、静态代理

首先我们先创建一个房主的接口(Houseowner),接口中只有一个租房子的方法。

 /**
* @author wzy
* @version 1.0
* @date 2019/5/9 15:31
*/
public interface Homeowner {
public void letHouse();
}

之后我们定义一个类去实现这个接口

 /**
* @author wzy
* @version 1.0
* @date 2019/5/9 15:22
*/
public class HomeownerImpl implements Homeowner { public void letHouse() {
System.out.println("房东:出租了一套房子");
}
}

房主出租房子一般都会交给中介代理,创建一个AgencyProxy类,我们可以看到下面的类,这个类实现了被Homeowner接口,将房主的实现类作为类的成员变量,并且在自己的letHouse方法中调用目标类的方法,并且可以在调用目标类的前后做一些操作。

 public class AgencyProxy implements Homeowner{
//被代理的对象
private HomeownerImpl target; public AgencyProxy(HomeownerImpl target) {
this.target = target;
} public void letHouse() {
System.out.println("中介带租客看房子");
target.letHouse();
System.out.println("成交后中介收取服务费");
} }

接下来,创建一个租客类Tenant进行测试

 public class Tenant {
public static void main(String[] args) {
//租房子
HomeownerImpl homeowners = new HomeownerImpl();
AgencyProxy agencyProxy = new AgencyProxy(homeowners);
agencyProxy.letHouse(); }
}

输出结果:

我们可以看到输出的结果,在调用被代理类的方法前后,代理类都可以做一些操作,这样就可以达到解耦的目的,也可以保护被代理的对象的目的,现在我们思考一下,如果被代理类的方法很多,那么我们每次都要在代理类中将所有方法重写一遍吗?并且如果被代理类中的方法名称发生变化,我们就需要去修改代理类的代码,这显然是不科学的,然而,动态代理就解决了这一问题。

3.动态代理

动态代理分为两种:JDK动态代理和cglib动态代理,动态代理的底层原理是,在程序运行时,通过反射机制动态生成代理类,那么如何实现动态代理呢?我们通过创建一个实现InvocationHandler的类,实现其中的invoke方法,在invoke方法对目标类中的方法进行调用。之后通过Proxy.newProxyInstance()创建一个动态代理的对象。

保持其他代码不动,修改AgencyProxy类的代码:

 public class AgencyProxy implements InvocationHandler{
//被代理的对象,目标类
private Homeowner target;
//通过构造函数传入被代理目标类
public AgencyProxy(Homeowner target) {
this.target = target;
} public Homeowner getProxy() {
//目标类的类加载
ClassLoader loader = target.getClass().getClassLoader();
//返回代理类的接口列表
Class [] classes = target.getClass().getInterfaces();
//最后一个参数返回的实现了InvocationHandler的代理类
Homeowner homeowner = (Homeowner) Proxy.newProxyInstance(loader, classes, this);
//返回代理类对象
return homeowner;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("中介在租房前操作。。。。");
//动态执行代理目标类中的方法
Object result = method.invoke(target);
System.out.println("中介在租房后的操作。。。");
return result;
}
}

修改租客类Tenant测试动态代理:

 public class Tenant {
public static void main(String[] args) {
//创建被代理类:房主类
Homeowner homeowners = new HomeownerImpl();
//创建代理类,并传入被代理对象
AgencyProxy agencyProxy = new AgencyProxy(homeowners);
//返回生成的对象
Homeowner homeownerProxy = agencyProxy.getProxy();
//调用方法
homeownerProxy.letHouse();
}
}

输出结果:我们可以看到通过动态代理我们实现了同样的效果。

4.总结

动态代理是一种十分常用的设计模式,在各种开源框架中都得到了非常广泛的应用,例如Spring的AOP底层就是使用的动态代理,MyBatis底层去代理Mapper使用的也是动态代理,还有就是在日志输出上也会用到这种设计模式,它的优势是实现无侵入式的代码扩展,也就是方法的增强;让你可以在不用修改源码的情况下,增强一些方法;在方法的前后你可以做你任何想做的事情(甚至不去执行这个方法都可以)。

Java设计模式之——代理设计模式的更多相关文章

  1. IOS设计模式第五篇之装饰设计模式的代理设计模式

    版权声明:原创作品,谢绝转载!否则将追究法律责任. 代理: 另一个装饰设计模式,代理,是一个代表或者协调另一个对象的行为机制.例如当你用一个tableView,你必须实现他里面的一个tableView ...

  2. java的动态代理设计模式

    代码实现: package com.lky.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Me ...

  3. java之动态代理设计模式

    代理:专门完成代理请求的操作类,是所有动态代理类的父类,通过此类为一个或多个接口动态地生成实现类. 弄清动态代理的关键是清楚java的反射机制,在https://www.cnblogs.com/xix ...

  4. java设计模式之代理设计模式(Proxy)

    一个简单Proxy代理模式范例 interface Subject{ //定义核心主题所要完成的功能 public void make(); } class RealSubject implement ...

  5. Java代理设计模式(Proxy)的四种具体实现:静态代理和动态代理

    面试问题:Java里的代理设计模式(Proxy Design Pattern)一共有几种实现方式?这个题目很像孔乙己问"茴香豆的茴字有哪几种写法?" 所谓代理模式,是指客户端(Cl ...

  6. java之 代理设计模式

    1. 设计一个案例来实现租房功能.分析:在租房的过程中涉及到了3个对象,房东,中介,房客. 中介和房客具有相同的功能--租房. 可以设计如下: 2.上图的设计实际上就是一个代理设计模式---静态代理设 ...

  7. ios代理设计模式

    代理设计模式的作用:     1.A对象监听B对象的一些行为,A成为B的代理     2.B对象想告诉A对象一些事情,A成为B的代理   代理设计模式的总结:     如果你想监听别人的一些行为,那么 ...

  8. Java三种代理模式:静态代理、动态代理和cglib代理

    一.代理模式介绍 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能. 简言之,代理模式就是 ...

  9. java --- 设计模式 --- 动态代理

    Java设计模式——动态代理 java提供了动态代理的对象,本文主要探究它的实现, 动态代理是AOP(面向切面编程, Aspect Oriented Programming)的基础实现方式, 动态代理 ...

随机推荐

  1. logstash之Input插件

    1:stdin标准输入和stdout标准输出 首先执行命令: bin/logstash -e 'input { stdin { } } output { stdout { codec   => ...

  2. nowcoder---常州大学新生寒假训练会试----F 大佬的生日礼包(二分)

    链接:https://www.nowcoder.net/acm/contest/78/F 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit ...

  3. http常用标签

    HTML标签大全(常用)   文本标记语言,即HTML(Hypertext Markup Language),是用于描述网页文档的一种标记语言. HTML之所以称为超文本标记语言,是因为文本中包含了所 ...

  4. jQuery.parseJSON()

    https://api.jquery.com/jQuery.parseJSON/ https://api.jquery.com/category/deprecated/deprecated-3.0/ ...

  5. xsens melodic ros driver

    sudo apt-get update sudo apt-get install ros-melodic-xsens-driver 设置数据输出: // 输出四元数,加速度.角速度.地磁 python ...

  6. Vue开发调试神器 vue-devtools

    Vue开发调试神器: vue-devtools 1. 下载Chrome扩展插件GitHub下载地址: https://github.com/vuejs/vue-devtools 建议使用npm淘宝镜像 ...

  7. Oracle 启用登录终端超时锁定功能

    远程连接oracle 会出现超时连接断开的问题,所以需要修改oracle配置. 修改超时时间10分钟 ALTER PROFILE DEFAULT LIMIT IDLE_TIME 10; 查询修改后的超 ...

  8. python使用相对路径创建文件夹

    两个py文件,一个是al文件夹下的test1.py,一个是和al文件夹同层的test2.py test1.py代码如下: import os def test(): path = './source_ ...

  9. 【ABAP系列】SAP ABAP SY-SUBRC的含义解析

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP SY-SUBR ...

  10. SPA应用性能优化(懒加载)

    前提: 如今开发方式都是采用前后台分离的方式,前台采用的方式则是单页面应用开发简称SPA,这种开发模式最大的一个特点就是将有所代码打包成了一个文件, 这会导致了一个问题就是如果这个应用过大,打出来的这 ...