掘金 后端 ( ) • 2024-04-09 13:38

代理模式

代理模式是指由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

进一步阐述:代理模式的结构比较简单,主要是通过定义一个继承抽象主题的代理来包含真实主题,从而实现对真实主题的访问,本质上代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用。 代理模式包含三种角色:

  • Subject(抽象主题):通过接口或抽象类声明真实主题和代理对象实现的业务方法。
  • Real Subject(真实主题):实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
  • Proxy(代理):提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

案例:我们以金士顿内存条代理商为例,金士顿是内存条的生产商,但有无数个代理商卖金士顿的内存条,代理商对客户开放,客户给与购买价格后,代理商赚取差价,但客户是不知道真实的价格的。

UML类图:

代理模式.jpg

客户端Client类:

/**
 * 使用代理模式的客户端(模拟用户购买金士顿内存条)
 */
public class Client {
​
    public static void main(String[] args) {
        //客户向内存条代理商给了150元购买内存条
        MemoryModuleProxy memoryModuleProxy = new MemoryModuleProxy();
        memoryModuleProxy.sell(150);
    }
}

内存条MemoryModule接口:

/**
 * 内存条接口(抽象主题)
 */
public interface MemoryModule {
​
    /**
     * 出售内存条的方法
     */
    void sell(int money);
}

金士顿内存条KingstonMemoryModule类:

/**
 * 金士顿内存条(真实主题)
 */
public class KingstonMemoryModule implements MemoryModule {
​
    @Override
    public void sell(int money) {
        System.out.println("金士顿厂商以" + money +  "的金额出售内存条");
    }
}

内存条代理商MemoryModuleProxy类:

/**
 * 内存条代理商(代理)
 */
public class MemoryModuleProxy implements MemoryModule {
​
    /**
     * 持有金士顿内存条对象
     */
    private KingstonMemoryModule kingstonMemoryModule = new KingstonMemoryModule();
​
    @Override
    public void sell(int money) {
        preSell(money);
​
        //调用金士顿内存条的销售方法,默认金士顿厂商100元
        kingstonMemoryModule.sell(100);
​
        postSell(money);
    }
​
    /**
     * 打印代理商收取用户的钱(私有方法,让客户不可见)
     */
    private void preSell(int money) {
        System.out.println("代理商收取了客户" + money + "元钱");
    }
​
    /**
     * 打印代理商赚的钱(私有方法,让客户不可见)
     */
    private void postSell(int money) {
        System.out.println("代理商赚取了客户" + (money - 100) + "元钱");
    }
}

总结:

  • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用。
  • 代理对象可以扩展目标对象的功能。代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性。
  • 代理模式会造成系统设计中类的数量增加,在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;增加了系统的复杂度。

典型运用场景举例: 当无法或不想直接引用某个对象或访问某个对象存在困难时,可以通过代理对象来间接访问。使用代理模式主要有两个目的: 一是保护目标对象,二是增强目标对象。例如:Spring AOP中就是基于代理模式来做到方法的增强,但使用的是动态代理技术。代理模式本身属于静态代理技术,动态代理是静态代理的升级。