结构型--代理模式(Proxy)
一、代理模式是什么?
代理模式属于GOF23设计模式中结构型中的设计模式,通过代理对象来屏蔽(部分或者屏蔽)对真实对象的直接访问,下图为UML图:
在代理模式中组件包括:抽象角色接口、代理角色类、真实角色类。
抽象角色:声明真实对象和代理对象的共同接口。
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
实际上代理又分为动态代理和静态代理,在实际开发中使用比较多的是动态代理。在主题三种将分别对动态代理和静态代理给出具体的示例。
所谓的静态代理就是由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。而动态代理就是在程序运行时运用反射机制动态创建而成。
二、为什么用代理模式
1、远程代理,为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
2、虚拟代理,根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。例如,网页中在图片出来以前现出来文字。
3、安全代理,用来控制真实对象访问时的权限。
4、智能代理,是指当调用真实的对象时,代理处理另外一些事。
注:代理模式是AOP编程的核心实现之一。
三、怎么用代理模式
3.1:静态代理示例
源码已经上传GitHub:https://github.com/wanyouxian/DesignPatterns,工程名为:StaticProxy
定义抽象角色接口:
package com.rocky.staticproxy; public interface IRenting
{
/*
* 看房子
*/
public void watchingHouse(); /**
* 签合同
*/
public void signContract(); /**
* 取钥匙
*/
public void takeKey();
}
定义代理对象类,实现抽象角色接口,该类持有真实对象引用
package com.rocky.staticproxy; public class HouseProxy implements IRenting
{ private IRenting landLord = null; public HouseProxy(IRenting landLord)
{
this.landLord = landLord;
} @Override
public void watchingHouse()
{
System.out.println("HouseProxy.watchingHouse");
} @Override
public void signContract()
{
landLord.signContract();
} @Override
public void takeKey()
{
System.out.println("HouseProxy.takeKey");
}
}
定义真实对象类,实现抽象接口
package com.rocky.staticproxy; public class LandLord implements IRenting
{ @Override
public void watchingHouse()
{
System.out.println("LandLord.watchingHouse");
} @Override
public void signContract()
{
System.out.println("LandLord.signContract");
} @Override
public void takeKey()
{
System.out.println("LandLord.takeKey");
}
}
编写测试类
package com.rocky.testdriver; import com.rocky.staticproxy.HouseProxy;
import com.rocky.staticproxy.IRenting;
import com.rocky.staticproxy.LandLord; public class TestDriver
{ public static void main(String[] args)
{
IRenting landLord = new LandLord();
IRenting houseProxy = new HouseProxy(landLord); houseProxy.watchingHouse(); houseProxy.signContract(); houseProxy.takeKey();
} }
3.2:动态代理示例
动态代理有多种实现方式,并且在开发中实际使用的比较多,特别是AOP编程的核心实现机制。AOP动态代理主要是通过jdk动态代理和cglib动态代理实现,jdk动态代理是由Java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。下面示例中通过JDK实现动态代理作为演示demo,源码已经上传GitHub:https://github.com/wanyouxian/DesignPatterns,工程名为:DynamicProxy
定义抽象角色:
package com.rocky.dynamicproxy; public interface IRenting
{
/*
* 看房子
*/
public void watchingHouse(); /**
* 签合同
*/
public void signContract(); /**
* 取钥匙
*/
public void takeKey();
}
定义真实对象类:
package com.rocky.dynamicproxy; public class LandLord implements IRenting
{ @Override
public void watchingHouse()
{
System.out.println("房东把房子挂到中介");
} @Override
public void signContract()
{
System.out.println("房东自己签租房合同"); } @Override
public void takeKey()
{
System.out.println("中介把房子钥匙给房客"); } }
定义代理对象处理器:
package com.rocky.dynamicproxy; public class LandLord implements IRenting
{ @Override
public void watchingHouse()
{
System.out.println("房东把房子挂到中介");
} @Override
public void signContract()
{
System.out.println("房东自己签租房合同"); } @Override
public void takeKey()
{
System.out.println("中介把房子钥匙给房客"); } }
编写测试类:
package com.rocky.testdriver; import java.lang.reflect.Proxy; import com.rocky.dynamicproxy.IRenting;
import com.rocky.dynamicproxy.LandLord;
import com.rocky.dynamicproxy.RentInvocationHandler; public class TestDriver
{ public static void main(String[] args)
{
IRenting landLord = new LandLord();
RentInvocationHandler handler = new RentInvocationHandler(landLord); IRenting proxy = (IRenting) Proxy.newProxyInstance(landLord.getClass().getClassLoader(),
landLord.getClass().getInterfaces(), handler); proxy.watchingHouse();
proxy.signContract();
proxy.takeKey();
} }
结构型--代理模式(Proxy)的更多相关文章
- JAVA设计模式(09):结构型-代理模式(Proxy)
代理模式是经常使用的结构型设计模式之中的一个,当无法直接訪问某个对象或訪问某个对象存在困难时能够通过一个代理对象来间接訪问,为了保证client使用的透明性,所訪问的真实对象与代理对象须要实现同样的接 ...
- 结构型---代理模式(Proxy Pattern)
代理模式的详细介绍 代理模式按照使用目的可以分为以下几种: 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象.这个不同的地址空间可以是本电脑中,也可以在另一台电脑中.最典型 ...
- 代理模式/proxy模式/结构型模式
代理模式proxy 定义 为其他对象提供一种代理,并以控制对这个对象的访问.最简单的理解,买东西都是要去商店的,不会去工厂. java实现三要素 proxy(代理)+subject(接口)+realS ...
- 【转】设计模式(十一)代理模式Proxy(结构型)
设计模式(十一)代理模式Proxy(结构型) 1.概述 因为某个对象消耗太多资源,而且你的代码并不是每个逻辑路径都需要此对象, 你曾有过延迟创建对象的想法吗 ( if和else就是不同的两条逻辑路径) ...
- 代理模式 PROXY Surrogate 结构型 设计模式(十四)
代理模式 PROXY 别名Surrogate 意图 为其他的对象提供一种代理以控制对这个对象的访问. 代理模式含义比较清晰,就是中间人,中介公司,经纪人... 在计算机程序中,代理就表示一个客户端不想 ...
- 设计模式系列之代理模式(Proxy Pattern)——对象的间接访问
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- 代理模式(Proxy pattern)
代理模式(proxy pattern):作用:为其他对象提供一种代理,以控制对这个对象的访问.代理对象在客户端对象和目标对象之间起中介的作用. 代理模式涉及到的角色: 抽象角色:声明真实对象和代理对象 ...
- 13.代理模式(Proxy Pattern)
using System; namespace Test { //抽象角色:声明真实对象和代理对象的共同接口. //代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象, //同时代理 ...
- 大熊君说说JS与设计模式之------代理模式Proxy
一,总体概要 1,笔者浅谈 当我们浏览网页时,网页中的图片有时不会立即展示出来,这就是通过虚拟代理来替代了真实的图片,而代理存储了真实图片的路径和尺寸,这就是代理方式的一种. 代理模式是比较有用途的一 ...
随机推荐
- VUE随笔-20181020
常用的一些指令 -------------------------------------------------------------------------------------------- ...
- 【lojg152】 乘法逆元 2(数学)
题面 传送门 题解 orz Wa自动机 这是一个可以\(O(n)\)求出\(n\)个数逆元的方案 先把所有的数做一个前缀积,记为\(s_i\) 然后我们用快速幂求出\(s_n\)的逆元,记为\(sv_ ...
- mysqli扩展库应用---批量执行sql语句
1, mysqli批量执行sql语句.基本语法: $sqls=”sql1;sql2;………” mysqli::multi_query($sqls); 同一个$sqls要么是增删改语句集合,要么是查询语 ...
- 5,临界区 之 lock
前提背景:多个并发线程共享同一个资源时,为防止这些共享资源可能出现的错误或数据不一致问题,提出了临界区的概念 临界区: 指一个用以访问共享资源的代码块,这个代码块在同一时间内只能允许一个线程访问 实现 ...
- request.getSession()、reqeust.getSession(false)和request.getSession(true)
getSession()/getSession(true):当session存在时返回该session,否则新建一个session并返回该对象 getSession(false):当session存在 ...
- Jquery sblings
$("给定元素").siblings(".selected") 中的(".selected")表示筛选给定元素类名为.selected的同胞 ...
- centOS7虚拟机设置固定IP
说明:想要达到的如下效果, 1.笔记本主机IP为设置自动获取,不管什么情况下,不受虚拟机影响,只要连接外网就可以正常上网: 2.只要笔记本主机可以正常访问外网,启动虚拟机中的CentOS 7系统就 ...
- spring测试save方法报错
用test类测试service的save方法时,报错如下: 2018-08-24 21:52:13,506 - could not read a hi value com.mysql.jdbc.exc ...
- Angular material mat-icon 资源参考_Places
ul,li>ol { margin-bottom: 0 } dt { font-weight: 700 } dd { margin: 0 1.5em 1.5em } img { height: ...
- shell (3) 磁盘挂载
#!/bin/sh disk=`df -h |grep /dev/sd|awk '{print $1}'` echo $disk for d in $disk do echo $d uuid=`blk ...