结构型--代理模式(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,笔者浅谈 当我们浏览网页时,网页中的图片有时不会立即展示出来,这就是通过虚拟代理来替代了真实的图片,而代理存储了真实图片的路径和尺寸,这就是代理方式的一种. 代理模式是比较有用途的一 ...
随机推荐
- javap -- Java 类文件解析器
参考文档 http://blog.chinaunix.net/uid-692788-id-2681132.html http://docs.oracle.com/javase/7/docs/techn ...
- 箭头函数中的this和普通函数中的this对比
ES6中新增了箭头函数这种语法,箭头函数以其简洁性和方便获取this的特性.下面来总结一下他们之间的区别: 普通函数下的this: 在普通函数中的this总是代表它的直接调用者,在默认情况下,this ...
- sql charIndex用法
CHARINDEX(): 写SQL语句我们经常需要判断一个字符串中是否包含另一个字符串,但是SQL SERVER中并没有像C#提供了Contains函数,不过SQL SERVER中提供了一个叫CHAE ...
- Saiku2.6 保存查询后,重新打开报 Error Loading Query错误。
发现Saiku2.6的查询保存后重新打开就会报如下错误,同等的Schema文件和数据库环境在3.15环境里面打开是一切正常的. 后面对比了一下2.6和3.15的启动环境,发现有些差异的地方. 2.6启 ...
- [原创] 项目 watch EMFILE 报错处理过程
目录 事件 处理过程 参考资料 小知识点 单进程文件句柄限制 系统总文件句柄限制 inotify 文件系统事件监控 事件 公司XX游戏 S114服启动失败(使用 pomelo - node.js 框架 ...
- 进阶篇:2.1)DFMA实施障碍和关键
本章目的:了解DFMA实施障碍与关键. 1.实施的障碍 面向制造和装配的产品开发能够降低产品成本.提高产品质量.缩短产品开发周期,但是,由于传统产品开发思想和各种条件的限制,实施面向制造和装配的产品开 ...
- Educational Codeforces Round 58 (Rated for Div. 2)
A. Minimum Integer 水 #include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using name ...
- redis的主从同步
一.redis的主从操作流程 1. 准备三个redis配置文件 #进入redis的配置文件夹,准备好这几个文件,6379不用管,默认的,和这次操作无关 [root@qishi ~]# cd /etc/ ...
- AXI协议(一)
最近弄Zynq,不懂AXI协议Zynq很难玩儿的转.这些笔记主要攻克AXI中的一些难题. 所有的AXI4包含了5个不同的通道: (1)读/写地址通道(Read/Write address ch ...
- leetcode有意思的题目总结
231. 2的幂 2^3=8 得 8是2的幂 判断一个整数是不是2的幂,可根据二进制来分析.2的幂如2,4,8,等有一个特点: 二进制数首位为1,其他位为0,如2为10,4为100 2&(2 ...