什么是代理

代理就是给目标对象一个代理对象,并又代理对象控制目标的引用.

为什么使用代理模式

  1. 通过引入代理对象的方式,间接访问目标对象,避免不必要的复杂性.
  2. 通过代理对象可以对原有的业务实现增强.

举例:如果我们需要买国外的某一件商品A,这个时候我们一般有两个途径要么直接去国外买,要么可以找一些代购人员帮我们去购买。在这种情况下,我们由于直接去国外买,实在是太耗软妹币,而且还要花时间等等,这个时候我们最优的选择就是找代购购买,这样也帮我们省去了很多麻烦的事情。

image-20210719142855948

image-20210719143547015

代码示例

接口:

public interface ITargetFactoryService {
    void sale(String name);
}

目标对象:

public class TargetFactoryServiceImpl implements ITargetFactoryService {
    @Override
    public void sale(String name) {
        log.info(name+"购买了商品A");
    }
}

代理对象:

public class ProxyImpl implements ITargetFactoryService {
    public ITargetFactoryService service;
    
    public ProxyImpl(ITargetFactoryService service){
        super();
        this.service = service;
    }

    @Override
    public void sale(String name) {
        before();
        service.sale("代购");
        after();

    }

    /**
     * 后置增强
     */
    private void after() {
        log.info("代购在购买后得到了市场调研结果");
    }

    /**
     * 前置增强
     */
    private void before() {
        log.info("代购在购买前做了市场调研");
    }
}

测试类:

public class SpsringJdbcApplication {
  public static void main(String[] args) {
    TargetFactoryServiceImpl service = new TargetFactoryServiceImpl();
    ProxyImpl proxy = new ProxyImpl(service);
    proxy.sale("代购");
    SpringApplication.run(SpsringJdbcApplication.class, args);
  }
}

测试结果:

image-20210719144445707

通过示例可以看到,代理对象包含了目标对象,并且在业务处理上进行了一定的业务扩展,但却和目标对象继承于同一个接口.

这种情况便是静态代理,适合业务情况比较简单,实现类少,需求变化不频繁,但是要对原有目标服务对象进行功能扩展,并且不修改原有服务,这个时候我们可以选择使用静态代理.

静态代理的缺点

如果此时业务继续扩展,在经过一定的调研之后,发现商品B更加收欢迎,这个时候我们就需要对业务继续进行扩展.

接口

public interface ITargetFactoryBService {
    void saleB(String name);
}

目标对象

public class ITargetFactoryBServiceImpl implements ITargetFactoryBService {
    @Override
    public void saleB(String name) {
        log.info(name + "购买了商品B");
    }
}

代理对象

public class ProxyTwoImpl implements ITargetFactoryService, ITargetFactoryBService {

    public ITargetFactoryService service;

    public ITargetFactoryBService bService;

    public ProxyTwoImpl(ITargetFactoryService service,ITargetFactoryBService bService){
        super();
        this.service = service;
        this.bService = bService;
    }

    @Override
    public void sale(String name) {
        before();
        service.sale("代购");
        after();

    }

    @Override
    public void saleB(String name) {
        before();
        bService.saleB("代购");
        after();
    }

    /**
     * 后置增强
     */
    private void after() {
        log.info("代购在购买后得到了市场调研结果");
    }

    /**
     * 前置增强
     */
    private void before() {
        log.info("代购在购买前做了市场调研");
    }
}

测试类:

public class SpsringJdbcApplication {
  public static void main(String[] args) {
    TargetFactoryServiceImpl service = new TargetFactoryServiceImpl();
    ITargetFactoryBServiceImpl bService = new ITargetFactoryBServiceImpl();
    ProxyTwoImpl proxy2 = new ProxyTwoImpl(service, bService);
    proxy2.sale("代购");
    proxy2.saleB("代购");
    SpringApplication.run(SpsringJdbcApplication.class, args);
  }
}

测试结果:

image-20210719145739169

在进行业务扩展时,需要对原有的代理类进行修改,如果后期需要更多的业务时,这个类将变得繁杂,大量的继承以及重写,牵一发而动全身,所以这种业务扩展性高,业务变化繁杂的情况不适合使用静态代理.

总结

  1. 违反Java设计模式开闭原则,即:程序对外扩展开放,对修改关闭.当要进行变更时,应该是新增代码来实现,而不是在原有代码上进行修改.
  2. 扩展性差.
  3. 可维护性差.
  4. 代码耦合度高.

参考:

文章:https://www.cnblogs.com/staticking/p/13628267.html