智能的代理模式,让职责变得更加清晰!

一、代理模式的定义

        代理模式是一种使用率非常高的模式,也叫做委托模式,当然很多设计模式如状态模式、策略模式、访问者模式本质上都是采用了委托模式,只是在特殊的场合进行使用。它的定义如下:

        为其他对象提供一种代理以控制对这个对象的访问。

        代理模式中有三种角色:

(1)Subject抽象主题角色

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

(2)RealSubject具体主题角色

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

(3)Proxy代理主题角色

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

        

 

二、代理模式的通用代码

抽象主题类

public interface Subject{
  //定义一个方法
  public void request();
}

真实主题类

public class RealSubject implements Subject{
  //实现方法
  public void request(){
    //业务逻辑处理
  }
}

代理类

public class Proxy implements Subject{
  //要代理哪个实现类
  private Subject subject = null;
  //默认被代理者
  public Proxy(){
    this.subject=new Proxy();
  }
  //通过构造函数传递代理者
  public Proxy(Object ..objects){
   
  }
  //实现接口中定义的方法
  public void request(){
    this.before();
    this.subject.request();
    this.after();
  }
  //预处理
  private void before(){
    //do something
  }
  //善后处理
  private void after(){
    //do something
  }
}

        一个代理类可以代理多个被委托者或被代理者,一个接口只需要一个代理类就可以,具体代理哪个实现类由高层模块来决定,通过构造函数传递对谁进行代理。

public Proxy(Subject subject) {
    this.subject = subject;
}

 

三、代理模块的应用 

代理模式的优点

  • 职责清晰

        真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件事务。

  • 高扩展性

        具体主题角色是随时都会发生变化的,只要它实现了接口,不管它如何变化,都逃不脱接口,那我们的代理类完全就可以在不做任何修改的情况下使用。

  • 智能化

        通过动态代理体现

代理模式的使用场景

        代理的目的是在目标对象方法的基础上做增强,而增强的本质是对目标对象的方法进行拦截和过滤。因此只要符合这种需求的情况均可以使用代理模式来实现。例如 Spring AOP(面向切面编程,核心是采用了动态代理机制)。

 

四、代理模式的扩展

1. 普通代理和强制代理

普通代理:在该模式下,调用者只知代理而不用知道真实的角色是谁,屏蔽了真实角色的变更对高层模块的影响。

        

 普通代理的抽象主题类:

public interface IGamePlayer {
    public void login(String user, String password);
    public void killBoss();
    public void upgrade();
}

普通代理的真实主题类:

public class GamePlayer implements IGamePlayer {
    private String name = "";
    public GamePlayer(IGamePlayer gamePlayer, String name) throws Exception {
        if (gamePlayer == null) {
            throw new Exception("不能创建真实角色!");
        } else {
            this.name = name;
        }
    }

    public void login(String user, String password) {
        System.out.println("登录名为" + user + "的用户" + this.name + "登录成功!");
    }

    public void killBoss() {
        System.out.println(this.name + "在打怪!");
    }

    public void upgrade() {
        System.out.println(this.name + "又升了一级!");
    }

}

普通代理的代理类:

public class GamePlayerProxy implements IGamePlayer {
    private IGamePlayer gamePlayer = null;

    public GamePlayerProxy(String name) {
        try {
            gamePlayer = new GamePlayer(this, name);
        }catch (Exception e) {
            // TODO: handle exception
        }
    }

    public void login(String user, String password) {
        this.gamePlayer.login(user, password);
    }

    public void killBoss() {
        this.gamePlayer.killBoss();
    }

    public void upgrade() {
        this.gamePlayer.upgrade();
    }

}

         调用者只需要创建一个代理对象,然后就可以正常进行调用。

public class Client {
    public static void main(String[] args) {
        IGamePlayer proxy = new GamePlayerProxy("张三");
        proxy.login("zhangsan", "admin");
        proxy.killBoss();
        proxy.upgrade();
    }
}

强制代理:在该模式下,由真实角色管理代理角色。只有通过真实角色指定的代理类才可以访问。也就是说,你必须通过真实角色查找到代理角色,否则你将不能访问。

        

 强制代理的抽象主题类:

public interface IGamePlayer {
    public void login(String user, String password);
    public void killBoss();
    public void upgrade();
    public IGamePlayer getProxy();  //获取代理
}

强制代理的真实主题类:

public class GamePlayer implements IGamePlayer {
    private String name = "";
    private IGamePlayer proxy = null;

    public GamePlayer(String name) {
        this.name = name;
    }

    @Override
    public void login(String user, String password) {
        if (isProxy()) {
            System.out.println("登录名为" + user + "的用户" + this.name + "登录成功!");
        } else {
            System.out.println("请使用指定的代理访问");
        }

    }

    @Override
    public void killBoss() {
        if (isProxy()) {
            System.out.println(this.name + "在打怪!");
        } else {
            System.out.println("请使用指定的代理访问");
        }
    }

    @Override
    public void upgrade() {
        if (isProxy()) {
            System.out.println(this.name + "又升了一级!");
        } else {
            System.out.println("请使用指定的代理访问");
        }
    }

    @Override
    public IGamePlayer getProxy() {
        this.proxy = new GamePlayerProxy(this);
        return this.proxy;
    }

    //检验是否是代理访问
    private boolean isProxy() {
        if (this.proxy == null) {
            return false;
        } else {
            return true;
        }
    }

}

 强制代理的代理类:

public class GamePlayerProxy implements IGamePlayer{
    private IGamePlayer gamePlayer=null;
    public GamePlayerProxy(IGamePlayer gamePlayer) {
        this.gamePlayer = gamePlayer;
    }

    @Override
    public void login(String user, String password) {
        this.gamePlayer.login(user, password);
    }

    @Override
    public void killBoss() {
        this.gamePlayer.killBoss();
    }

    @Override
    public void upgrade() {
        this.gamePlayer.upgrade();
    }

    @Override
    public IGamePlayer getProxy() {
        return this;
    }

}

        调用者此时不能够再通过直接创建代理对象的方式进行调用了,而是首先创建一个主题对象,然后通过主题对象指定代理,从而创建一个代理对象,然后进行调用。

public class Client {
    public static void main(String[] args) {
        IGamePlayer player = new GamePlayer("张三");
        IGamePlayer proxy = player.getProxy();
        proxy.login("zhangsan", "admin");
        proxy.killBoss();
        proxy.upgrade();
    }
}

2. 静态代理和动态代理

静态代理:需要手动实现代理类

动态代理:代理类不需要手动实现,而是自动实现。在实现阶段不需要关心代理谁,而在运行阶段才指定代理哪一个对象。

        由于动态代理的内容比较多,后续将单独写一篇博客来介绍相关内容,敬请期待!

发布了67 篇原创文章 · 获赞 69 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_34519487/article/details/104255180