zoukankan      html  css  js  c++  java
  • 代理模式

    代理模式(Proxy Pattern)

    定义:Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供一种代理以控制对这个对象的访问。一个类代表另一个类的功能。这种类型的设计模式属于结构型模式)

    主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

    何时使用:想在访问一个类时做一些控制。

    如何解决:增加中间层。

    关键代码:实现与被代理类组合。

    应用实例: 1、Windows 里面的快捷方式。 2按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理 9、spring aop。

    优点: 1、职责清晰。 2、高扩展性。 3、智能化。

    缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

    为什么要用代理模式?

    • 中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
    • 开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。

    使用场景:按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。

    注意事项: 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。

    ● Subject抽象主题角色

    抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求。

    ● RealSubject具体主题角色

    也叫做被委托角色、被代理角色。它才是冤大头,是业务逻辑的具体执行者。

    ● Proxy代理主题角色

    也叫做委托类、代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作。

    普通代理和强制代理:

    普通代理就是我们要知道代理的存在,也就是类似的GamePlayerProxy这个类的存在,然后才能访问;

    强制代理则是调用者直接调用真实角色,而不用关心代理是否存在,其代理的产生是由真实角色决定的。

    普通代理:

    在该模式下,调用者只知代理而不用知道真实的角色是谁,屏蔽了真实角色的变更对高层模块的影响,真实的主题角色想怎么修改就怎么修改,对高层次的模块没有任何的影响,只要你实现了接口所对应的方法,该模式非常适合对扩展性要求较高的场合。

    实现

    步骤 1

    /*
    创建服务类接口
    */
    public interface BuyBook {

    void addbuyBook();

    }

    步骤 2

    /*
    实现服务接口
    */
    public class BuyBookImpl implements BuyBook {

    public void addbuyBook()
    {

    System.out.println("我要买书:数学");
    }
    }

    步骤 3

    /*
    创建代理类
    */
    public class BuyBookProxy implements BuyBook {


    BuyBook buyBook =null;
    public BuyBookProxy(final BuyBook buyBook)
    {
    this.buyBook=buyBook;

    }

    public void addbuyBook() {

    System.out.println("买书选择中");

    buyBook.addbuyBook();
    System.out.println("买书成功");
    }

    }

    步骤 4 测试

    public static void main(String[] arg) {
    BuyBook buy = new BuyBookImpl();
    buy.addbuyBook();


    BuyBookProxy buyBookProxy = new BuyBookProxy(buy);
    buyBookProxy.addbuyBook();
    }

    结果:

    买书选择中
    我要买书:数学
    买书成功

    强制代理:

    强制代理的概念就是要从真实角色查找到代理角色,不允许直接访问真实角色。高层模块只要调用getProxy就可以访问真实角色的所有方法,它根本就不需要产生一个代理出来,代理的管理已经由真实角色自己完成。

    动态代理:

    根据被代理的接口生成所有的方法,也就是说给定一个接口,动态代理会宣称“我已经实现该接口下的所有方法了”。

    两条独立发展的线路。动态代理实现代理的职责,业务逻辑Subject实现相关的逻辑功能,两者之间没有必然的相互耦合的关系。通知Advice从另一个切面切入,最终在高层模块也就是Client进行耦合,完成逻辑的封装任务。

    实现(在动态代理中我们不再需要再手动的创建代理类,我们只需要编写一个动态处理器就可以了。真正的代理对象由JDK再运行时为我们动态的来创建)

    步骤 1

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

    public class DynamicProxyHandler implements InvocationHandler {

    private Object object;

    public DynamicProxyHandler(final Object object) {
    this.object = object;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object result = method.invoke(object, args);
    return result;
    }
    }
    步骤 2
    /*

    代理模式(Proxy Pattern)
    动态代理
    */
    public class ProxyPatternDescription {

    public static void main(String[] arg) {
    BuyBook buy = new BuyBookImpl();
    BuyBook proxyBuyHouse = (BuyBook) Proxy.newProxyInstance(BuyBook.class.getClassLoader(), new
    Class[]{BuyBook.class}, new DynamicProxyHandler(buy));
    proxyBuyHouse.addbuyBook();
    }
    }

    结果:

    我要买书:数学

    动态代理的意图:横切面编程,在不改变我们已有代码结构的情况下增强或控制对象的行为。 

    首要条件:被代理的类必须要实现一个接口。

  • 相关阅读:
    Linux手动安装Apache2.4
    Linux 定时任务 crontab
    微信小程序 wxs 使用正则替换字符串
    腾讯云 远程通过端口3306访问MYSQL数据库
    微信小程序点击内容展开隐藏评论文章等
    SGA设置
    oracle 序列
    oracle中lnnvl函数
    union 中null值合并原理
    oracle 事务读一致性(一)
  • 原文地址:https://www.cnblogs.com/shumeigang/p/13097599.html
Copyright © 2011-2022 走看看