设计模式之代理模式(结构型)

第一章

1.1 模式定义

代理模式:代理模式就是引入一个代理对象,通过代理对象实现对原对象的引用。代理模式是一种对象结构型。

1.2 代理模式包含如下角色

  • Subject:抽象主题角色
  • Proxy:代理主题角色
  • RealSubject:真实主题角色

1.3 模式例子

public class Proxy implements Subject
{
    private RealSubject realSubject = new RealSubject();
    public void preRequest()
    {…...}
    public void request()
    {
        preRequest();
        realSubject.request();
        postRequest();
    }
    public void postRequest()
    {……}
}

1.4 模式类型

来自:《设计模式》一书归纳分类

  • 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中,远程代理又叫做大使(Ambassador)。
  • 虚拟(Virtual)代理:如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
  • Copy-on-Write代理:它是虚拟代理的一种,把复制(克隆)操作延迟到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。
  • 保护(Protect or Access)代理:控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
  • 缓冲(Cache)代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
  • 防火墙(Firewall)代理:保护目标不让恶意用户接近。
  • 同步化(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。
  • 智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,如将此对象被调用的次数记录下来等。

下面介绍一下静态代理和动态代理

代理模式分为静态代理和动态代理 ? 静态代理:静态代理就是编译阶段就生成代理类来完成对代理对象的一系列操作。

? 动态代理:动态代理是指在运行时动态生成代理类。即,代理类的字节码将在运行时生成并载入当前代理的 ClassLoader。

第二章 静态代理

静态代理:静态代理就是编译阶段就生成代理类来完成对代理对象的一系列操作。

主题接口:

public   interface Subject  {
    abstract   public   void  request();
}   

目标对象:

public   class  RealSubject  implements Subject  {
   public   void  request()  {
       System.out.println( " From real subject. " );
   }
}  

代理对象:

public   class  StaticProxySubject  implements Subject  {
    private  RealSubject  realSubject;  // 以真实角色作为代理角色的属性
    public  ProxySubject()  { }
    public  void  request()  {  // 该方法封装了真实对象的request方法
    //懒加载,用的时候才加载
    if ( realSubject  ==   null  )  {
        realSubject  =   new  RealSubject();
    }
    realSubject.request();  // 此处执行真实对象的request方法
   }
}

编写客户端类:

public class Client{
    StaticProxySubject sps = new StaticProxySubject();
    sps.request();
}

第三章 动态代理

动态代理:动态代理是指在运行时动态生成代理类。即,代理类的字节码将在运行时生成并载入当前代理的 ClassLoader。

生成动态代理的方法有很多: JDK中自带动态代理,CGlib, javassist等。

3.1 JDK动态代理

Proxy类。该类即为动态代理类,该类最常用的方法为:public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

newProxyInstance()方法用于根据传入的接口类型interfaces返回一个动态创建的代理类的实例,方法中第一个参数loader表示代理类的类加载器,第二个参数interfaces表示被代理类实现的接口列表,第三个参数h表示所指派的调用处理程序类。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyInvocationHandler implements InvocationHandler {
    private Class<?> target;//委托类
    public MyInvocationHandler(Class<?> target){
        this.target=target;
    }
    //实际执行类bind
    public  Object bind(Class<?> target){
        //利用JDK提供的Proxy实现动态代理
        return  Proxy.newProxyInstance(target.getClassLoader(),
                new Class[]{target},this);
    }

    @Override
    public Object invoke(Object o, Method method, Object[] args) throws Throwable {
        /**代理环绕**/
        //执行实际的方法
        Object invoke = method.invoke(target, args);
        return invoke;
    }
}

3.2 CGLIB动态代理

CGLIB动态代理实现相关类需要在项目中导入 cglib-nodep-2.1_3.jar ,主要涉及两个类:

MethodInterceptor接口。它是代理实例的调用处理程序实现的接口,该接口中定义了如下方法:public Object intercept(Object proxy, Method method, Object[] arg2, MethodProxy mp);

intercept()方法中第一个参数proxy表示代理类,第二个参数method表示需要代理的方法,第三个参数args表示代理方法的参数数组,第四个参数mp用 来去调用被代理对象方法

package com.demo;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class MyInterceptor implements MethodInterceptor{
    private Object target; ;//代理的目标对象
    public MyInterceptor(Object target) {
        this.target = target;
    }
//proxy 在其上调用方法的代理实例    method拦截的方法    args  拦截的参数
 //invocation 用来去调用被代理对象方法
    @Override
    public Object intercept(Object proxy, Method method, Object[] args,
                                         MethodProxy invocation) throws Throwable {
        //1.记录日志 2.时间统计开始   3.安全检查
        Object retVal = invocation.invoke(target, args);
        //4.时间统计结束
        return retVal;
    }
//创建代理对象的方法
    public Object proxy(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();//该类用于生成代理类
        enhancer.setSuperclass(this.target.getClass());//设置父类
        enhancer.setCallback(this);//设置回调用对象为本身
        return enhancer.create();

   }
}

原文地址:https://www.cnblogs.com/mzq123/p/10292694.html

时间: 2024-10-12 06:14:48

设计模式之代理模式(结构型)的相关文章

一起学java设计模式--代理模式(结构型模式)

代理模式 应用软件所提供的桌面快捷方式是快速启动应用程序的代理,桌面快捷方式一般使用一张小图片来表示(Picture),通过调用快捷方式的run()方法将调用应用软件(Application)的run()方法.使用代理模式模拟该过程,绘制类图并编程实现. package ProxyPattern; interface Software { void run(); } class Application implements Software { public void run() { Syste

设计模式(十三): Proxy代理模式 -- 结构型模式

  设计模式(十一)代理模式Proxy(结构型) 1.概述 因为某个对象消耗太多资源,而且你的代码并不是每个逻辑路径都需要此对象, 你曾有过延迟创建对象的想法吗 ( if和else就是不同的两条逻辑路径) ? 你有想过限制访问某个对象,也就是说,提供一组方法给普通用户,特别方法给管理员用户?以上两种需求都非常类似,并且都需要解决一个更大的问题:你如何提供一致的接口给某个对象让它可以改变其内部功能,或者是从来不存在的功能? 可以通过引入一个新的对象,来实现对真实对象的操作或者将新的对象作为真实对象

Proxy代理模式(结构型模式)

1.问题 在面向对象系统中,有些对象由于某种原因(比如创建对象的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给调用者带来麻烦,那么如何在不损失接口透明性的情况下,解决这些麻烦? 2.解决方案 通过架设一层中间层,让这层中间层来解决上面的麻烦,也就是我们所说的代理.大致的结构转换图如下: 转换成 将一个复杂的系统A,通过假设一层中间层C,将A中的复杂度处理掉,并通过C向B提供一种更灵活,满足B需求的方案. 案例一..Net中WebService技术提供了很好的借鉴.代码

设计模式(十):Decorator装饰者模式 -- 结构型模式

1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类—这建立在额外的代码上. 通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是静态的,用户不能控制增加行为的方式和时机.如果  你希望改变一个已经初始化的对象的行为,你怎么办?或者,你希望继承许多类的行为,改怎么办?前一个,只能在于运行时完成,后者

设计模式(八):Bridge桥接模式 -- 结构型模式

1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度? 例子1:设想如果要绘制矩形.圆形.椭圆.正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色.绿色.蓝色等,此时至少有如下两种设计方案: •第一种设计方案是为每一种形状都提供一套各种颜色的版本. •第二种设计方案是根据实际需要对形状和颜色进行组合. 方案1: 方案2:  

设计模式(九):Composite组合模式 -- 结构型模式

1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面. 例子1:就是多级树形菜单. 例子2:文件和文件夹目录 2.问题 我们可以使用简单的对象组合成复杂的对象,而这个复杂对象有可以组合成更大的对象.我们可以把简单这些对象定义成类,然后定义一些容器类来存储这些简单对象.客户端代码必须区别对象简单对象和容器对象,而实际上大多数情况下用户认为它们是一样的.对这些类区别使用,使得程序更加复杂.递归使用的时候跟麻烦,而我们如何使用递归组合,使得用户不必对这些类进行区别呢? 3.

设计模式(十二): Flyweight享元模式 -- 结构型模式

说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面向对象技术可以很好地解决系统一些灵活性或可扩展性或抽象性的问题,但在很多情况下需要在系统中增加类和对象的个数.当对象数量太多时,将导致运行代价过高,带来性能下降等问题.比如:例子1:图形应用中的图元等对象.字处理应用中的字符对象等. 2.解决方案: 享元模式(Flyweight):对象结构型模式运用

设计模式(十一):FACADE外观模式 -- 结构型模式

1. 概述 外观模式,我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性.例子1:一个电源总开关可以控制四盏灯.一个风扇.一台空调和一台电视机的启动和关闭.该电源总开关可以同时控制上述所有电器设备,电源总开关即为该系统的外观模式设计. 2. 问题 为了降低复杂性,常常将系统划分为若干个子系统.但是如何做到各个系统之间的通信和相互依赖关系达到最小呢? 3. 解决方案 外观模式:为子系统中的一组接口提供一个一致的界面,

设计模式(十二)外观模式(结构型)

概述 外观模式,我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性.例子:一个电源总开关可以控制四盏灯.一个风扇.一台空调和一台电视机的启动和关闭.该电源总开关可以同时控制上述所有电器设备,电源总开关即为该系统的外观模式设计. 问题 为了降低复杂性,常常将系统划分为若干个子系统.但是如何做到各个系统之间的通信和相互依赖关系达到最小呢?  解决方案