结构型--代理模式(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,笔者浅谈 当我们浏览网页时,网页中的图片有时不会立即展示出来,这就是通过虚拟代理来替代了真实的图片,而代理存储了真实图片的路径和尺寸,这就是代理方式的一种. 代理模式是比较有用途的一 ...
随机推荐
- bzoj 4598: [Sdoi2016]模式字符串
题目描述 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每一位仍然是A到z的大写字母. Alice希望知道,有多少对结点&l ...
- [Flex] 组件Tree系列 —— 阻止用户点击选中Tree中分支节点
mxml: <?xml version="1.0" encoding="utf-8"?> <!--功能描述:阻止用户点击选中Tree中分支节点 ...
- springmvc初步配置
导包/添加依赖: <dependency> <groupId>org.springframework</groupId> <artifactId>spr ...
- windows本地搭建nginx+php+mysql+redis环境详细步骤
1.mysql的下载和安装 这个可参考我另外一篇文章:http://www.cnblogs.com/myIvan/p/9265645.html 2.php的下载和配置修改 下载地址:https://w ...
- P3366 (模板)最小生成树
2019-01-30 最小生成树基本算法 定义: 给定一个边带权的无向图G=(V,E),n=|V|,m=|E|,由V中全部n个定点和E中n-1条边构成的无向连通子图被称为G的一颗生成树. 边的权值之和 ...
- Flume启动运行时报错org.apache.flume.ChannelFullException: Space for commit to queue couldn't be acquired. Sinks are likely not keeping up with sources, or the buffer size is too tight解决办法(图文详解)
前期博客 Flume自定义拦截器(Interceptors)或自带拦截器时的一些经验技巧总结(图文详解) 问题详情 启动agent服务 [hadoop@master flume-1.7.0]$ ...
- NSInvocation 调用block clang代码转换c++
NSInvocation 调用block cpp 转换 fatal error: 'UIKit/UIKit.h' file not found https://blog.csdn.net/yst199 ...
- fetch网络请求 get 和 post
//在React Native中,使用fetch实现网络请求 /* fetch 是一个封装程度更高的网络API, 使用了Promise* Promise 是异步编程的一种解决方案* Promise 对 ...
- 51nod1238. 最小公倍数之和 V3(数论)
题目链接 https://www.51nod.com/Challenge/Problem.html#!#problemId=1238 题解 本来想做个杜教筛板子题结果用另一种方法过了...... 所谓 ...
- HTML学习-01
1.标签描述了基本的链接地址/链接目标,该标签作为HTML文档中所有的链接标签的默认链接. 2.如果<head>里面设置了base,那么后面的img图片需要添加的相对路径. 3.不能使用工 ...