java设计模式(10):代理模式(Proxy)
一,定义: 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。
二,其类图:
三,分类一:静态代理
1,介绍:也就是需要我们为目标对象编写一个代理对象,在编译期就生成了这个代理对象,然后通过访问这个代理,来实现目标对象某些功能。
2,简单应用:在这里我们看一个简单的登录登出的例子:
登录功能的接口:
- /**
- * 公共接口,目标对象和代理都来实现
- */
- public interface ILogin{
- //登录
- void login();
- //登出
- void logout();
- }
实现的目标接口:
- /**
- * 目标对象,实现公共接口,达到登录登出的功能
- */
- public class Reallogin implements ILogin{
- public void login(){
- try {
- Thread.sleep(3200);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("登录系统.....");
- }
- public void logout(){
- try {
- Thread.sleep(2200);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("退出系统....");
- }
- }
大家看见了,上边的方法中我们加入了线程的睡眠,因为我想通过代理模式来测试登录登出的时间,因为JAVA程序我们遵循OCP(对扩展开放,对修改关闭)原则,所以为了不修改原来代码,我们来采用静态代理模式:
Proxy(代理对象)的代码:
- /**
- * 代理对象,代理目标对象Reallogin
- */
- public class ProxyLogin implements ILogin{
- //此类中包含了目标对象
- private Reallogin target;
- //构造方法
- public ProxyLogin (Reallogin target){
- this.target = target;
- }
- @Override
- public void login() {
- //开始时间
- long begin = System.currentTimeMillis();
- target.login();
- //结束时间
- long end = System.currentTimeMillis();
- System.out.println("耗费时长"+(end-begin)+"毫秒");
- }
- @Override
- public void logout() {
- long begin = System.currentTimeMillis();
- target.logout();
- long end = System.currentTimeMillis();
- System.out.println("耗费时长"+(end-begin)+"毫秒");
- }
- }
好,通过代理模式,非常简单的实现了对登录登出时间的捕获,但是,假如客户突然要求我们对所有的类方法的时间进行捕获,那该怎么办呢?总不能每一个类,都写一个代理类,那样太麻烦了吧!怎么呢???
3,分析:通过这里例子以及扩展我们来看一下静态代理模式的缺点吧:
a,如果出现上边的需求,那么势必会出现类爆炸的结果;
b,当然捕捉方法执行时间的代码都一样,我们每个方法都写,每个类都写,这也是代码的重复,没有达到代码复用的效果,这也完全违背了面向对象设计的原则。
4,思考:防止出现类爆炸,使代码能够得到复用。我们能不能用一个代理类,来代理所有需要计算方法运行时间呢??? 看下边的动态代理模式。
四,动态代理
1,介绍:通过反射机制,利用JDK提供的Proxy类,在程序运行的时候在内存中根据目标对象来创建代理对象,避免了类爆炸的出现。代理方法只写一此,使代码得到了复用。
2,解决上边的问题:
a,代理方法的编写:
- /**
- * 此类需要实现InvocationHandler接口
- * 调用处理器,当代理对象调用代理方法的时候,注册在调用处理器中的invoke方法会自动调用。
- */
- public class TimerInvocationHandler implements InvocationHandler {
- //目标对象,通过反射机制获得
- private Object target;
- //构造方法
- public TimerInvocationHandler(Object target){
- this.target = target;
- }
- /**
- * 参数:
- * Object proxy:代理对象的引用,proxy变量中保存代理对象的内存地址(这个参数很少用)
- * Method method:目标对象的目标方法。
- * Object[] args:目标对象的目标方法执行的时候所需要实参。
- */
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
- //开始时间
- long begin = System.currentTimeMillis();
- //执行目标对象中的方法
- Object retValue = method.invoke(target, args);
- //结束时间
- long end = System.currentTimeMillis();
- //计算时间
- System.out.println("耗费时长"+(end-begin)+"毫秒");
- return retValue;
- }
- }
b,注意这里的测试程序的编写:
- /**
- * 注意:JDK内置的动态代理Proxy只能代理接口
- *(如果既想代理接口又想代理抽象类需要使用第三方组件:例如cglib)
- */
- public class Test {
- public static void main(String[] args) {
- //创建目标对象
- ILogin target = new ProxyLogin();
- //创建代理对象:通过JDK内置的动态代理类java.lang.reflect.Proxy完成代理对象的动态创建
- //参数:
- ClassLoader loader;
- 这里的类装载器主要是用来装载在内存中生成的那个临时的字节码,
- 代理类的类装载器需要和目标类的类装载器一致。
- Class[] interfaces;
- 代理类和目标类必须实现“同一些”接口。(一个类可以同时实现多个接口)
- InvocationHandler handler;
- 当代理对象调用代理方法的时候,“注册”在调用处理器中的invoke方法会自动调用。
- ILogin proxy = (IUserService)Proxy.newProxyInstance(target.getClass().getClassLoader(),new Class[]{IUserService.class},new TimerInvocationHandler(target));
- //通过执行代理对象的代理方法去执行目标对象的目标方法
- proxy.login();
- proxy.logout();
- }
- }
3,动态代理模式相对来说比较难了解,因为它运用了反射机制。但是想象现实生活中,还是挺容易理解的,例如,工作中介,相当于代理模式中的代理对象,它可以为不同人找不同的工作,我们可以没有见过咱们生活中每个人都有一个工作中介代理对象吧。所以这里可以理解为功能代理对象,即为所有类代理可以实现同一种功能,例如上边的捕捉时间。
五,动态模式解决Service层的JDBC代码,以及一些重复的代码:
大家都直到Service层是用来写业务代码的,但是当出现事物时,我们需要在业务层进行事物的开启,提交,回滚,结束,这样就有了JDBC代码了,而且都是重复的,怎么办呢,我们可以为这些利用事物的业务层利用代理模式来解决这个问题。
看一下这个service层中的方法,里边有JDBC代码,而且每个Servlet都需要写,非常不满足规范:
- public boolean saveEnterprise(Enterprise en, List<EnInv> eninvs) throws Exception {
- Connection conn =null;
- int count=0 ;
- try {
- //获取数据连接对象
- conn=DBUtil.getConnection();
- //事物的开始
- DBUtil.beginTransaction(conn);
- count=ienterpriserDao.InsertEnterpriseDao(en, eninvs);
- //事物的提交
- DBUtil.commitTransaction(conn);
- } catch (Exception e) {
- try {
- //事物的回滚
- DBUtil.rollbackTransaction(conn);
- } catch (SQLException e1) {
- e1.printStackTrace();
- }
- e.printStackTrace();
- }finally{
- try {
- //事物的结束
- DBUtil.endTransaction(conn);
- } catch (SQLException e) {
- e.printStackTrace();
- }
- DBUtil.close(conn, null, null);
- }
- return count==(1+eninvs.size());
通过Prox动态代理:
代理方法的编写:
- public class TransactionInvcationHandler implements InvocationHandler {
- //目标对象的创建
- private Object target;
- //编写构造方法,
- public TransactionInvcationHandler(Object target){
- this.target=target;
- }
- @Override
- /**
- * 利用事物的操作的调用事物处理
- */
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- Object retValue=null;
- Connection conn=null;
- try{
- conn=DBUtil.getConnection();
- //开启事物
- DBUtil.beginTransaction(conn);
- //执行目标对象的方法
- retValue=method.invoke(target, args);
- //提交事物
- DBUtil.commitTransaction(conn);
- }catch(Exception e ){
- //回滚事物
- DBUtil.rollbackTransaction(conn);
- e.printStackTrace();
- }finally{
- //关闭事物
- DBUtil.endTransaction(conn);
- DBUtil.close(conn, null, null);
- }
- return retValue;
- }
- }
这样这个Service就只需要写这两句话了:
- public boolean saveEnterprise(Enterprise en, List<EnInv> eninvs) throws Exception {
- int count=0 ;
- count=ienterpriserDao.InsertEnterpriseDao(en, eninvs);
- return count==(1+eninvs.size());
- }
当然Servlet的调用和上边的那个测试程序一样,我就不再写了。总而言之,动态代理模式模仿我们生活中的中介代理,使我们的程序代码达到了非常好的复用和分类清楚,非常实用。
代理模式的其他应用:
1,远程代理,为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
2,虚拟代理,根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。例如,网页中在图片出来以前现出来文字。
3,安全代理,用来控制真实对象访问时的权限。
4,智能代理,是指当调用真实的对象时,代理处理另外一些事。
总而言之,这次的学习,有感觉软件和我们生活是息息相关的,善于发现生活的点点滴滴,从软件中联想生活会理解的更深,学习的更好!!!!
java设计模式(10):代理模式(Proxy)的更多相关文章
- Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景
我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...
- java设计模式6——代理模式
java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...
- 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)
原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为 ...
- 夜话JAVA设计模式之代理模式(Proxy)
代理模式定义:为另一个对象提供一个替身或者占位符以控制对这个对象的访问.---<Head First 设计模式> 代理模式换句话说就是给某一个对象创建一个代理对象,由这个代理对象控制对原对 ...
- Java设计模式:代理模式(转)
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一 ...
- 大熊君说说JS与设计模式之------代理模式Proxy
一,总体概要 1,笔者浅谈 当我们浏览网页时,网页中的图片有时不会立即展示出来,这就是通过虚拟代理来替代了真实的图片,而代理存储了真实图片的路径和尺寸,这就是代理方式的一种. 代理模式是比较有用途的一 ...
- 二十四种设计模式:代理模式(Proxy Pattern)
代理模式(Proxy Pattern) 介绍为其他对象提供一个代理以控制对这个对象的访问. 示例有一个Message实体类,某对象对它的操作有Insert()和Get()方法,用一个代理来控制对这个对 ...
- Java基础-设计模式之-代理模式Proxy
代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理 ...
- Java设计模式之代理模式(Proxy)
前言: 最近在研究Retrofit开源框架的时候,其主要核心代码是通过注解标示参数,动态代理模式实现具体接口,反射机制进行参数解析,最终实现发送请求.其实之前在学习Xutils源码的时候,Xutils ...
- java设计模式之八代理模式(Proxy)
其实每个模式名称就表明了该模式的作用,代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你 ...
随机推荐
- TCP/IP、Http的区别--(转自任智康)
TPC/IP协议是传输层协议,主要解决数据如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据.关于TCP/IP和HTTP协议的关系,网络有一段比较容易理解的介绍:"我们在传输数据 ...
- MyBatis 动态SQL(十二)
动态条件查询 以下是我们数据库表 tb_user 的记录: 假设现在有一个需求,就是根据输入的用户年龄和性别,查询用户的记录信息.你可能会说,这太简单了,脑袋里立马蹦出如下的 SQL 语句: SELE ...
- 使用vue-i18n实现中英文切换(内含动态属性的绑定)
最近做学生管理系统,因为有国外的学生,所以要进行中英文切换,查了查Vue中使用vue-i18n插件能够实现网页的中英文切换,学习内容如下: 一.下载vue-i18n插件 npm install vue ...
- [转]CAP和BASE理论
1. CAP理论 2000年7月,加州大学伯克利分校的Eric Brewer教授在ACM PODC会议上提出CAP猜想.2年后,麻省理工学院的Seth Gilbert和Nancy Lynch从理论上证 ...
- 摄像头ISP系统原理(上)
摄像头ISP系统原理(上) ISP(Image Signal Processor),即图像信号处理器,用于处理图像信号传感器输出的图像信号.它在相机系统中占有核心主导的地位,是构成相机的重要设备. 主 ...
- Hashing散列注意事项
Hashing散列注意事项 Numba支持内置功能hash(),只需__hash__()在提供的参数上调用成员函数即可 .这使得添加对新类型的哈希支持变得微不足道,这是因为扩展APIoverload_ ...
- FFmpeg集成到GPU
FFmpeg集成到GPU GPU加速视频处理集成到最流行的开源多媒体工具中. FFmpeg是最流行的开源多媒体操作工具之一,它有一个插件库,可以应用于音频和视频处理管道的各个部分,并在世界各地得到广泛 ...
- 一文搞定Samba云服务器配置(阿里云)
石头门第五话桶子入侵SERN的时候,先是PowerShell连接远程服务器,然后突然就用图形化界面显示了远程的试验报告,就是来源于Samba(大概). 抱着以上的想法才买了个服务器并且配一下samba ...
- C# 强行锁定 第三方 外部 应用程序窗体窗口的分辨率尺寸大小 禁止鼠标拖拽改变窗口大小
我们也许会有一些奇怪的需求,比如说禁止一个外部程序的窗口大小更改. 如果我们没法修改外部程序的代码,那要怎么做呢? 当然,我们可以通过DLL注入目标程序的方式去Hook或registry一个事件来检测 ...
- GD32F330 | ADC实例 基于DMA方式
GD32F330 | ADC实例 基于DMA方式 简单记录一下 ADC多通道转换 DMA搬运 的使用,以 GD32F330G8U6 为例: 一.ADC 基础知识 12位ADC是一种采用逐次逼近方式的模 ...
