设计模式学习笔记(七) 代理模式

该篇是主要说明代理模式

定义

为其他对象提供一种代理以控制对这个对象的访问。
代理模式也叫作委托模式。

角色

1.Subject抽象主题角色

可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求。
代码如下:

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

2.RealSubject具体主题角色

也叫做被委托角色、被代理角色。是业务逻辑的具体执行者。
代码如下:

public class RealSubject implements Subject {
    // 实现方法
    @Override
    public void request() {
        System.out.println("调用我");
    }
}

3.Proxy代理主题角色

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

public class Proxy implements Subject {

    private Subject subject = null;
    // 默认被代理者
    public Proxy() {
        this.subject = new RealSubject();
    }
    public Proxy(Subject subject) {
        this.subject = subject;
    }
    @Override
    public void request() {
        this.before();
        this.subject.request();
        this.after();
    }
    // 预处理
    private void before(){
        System.out.println("before");
    }
    // 善后处理
    private void after(){
        System.out.println("after");
    }
}

代码执行及结果

执行代码

  public static void main(String[] args) {
    Proxy proxy = new Proxy();
      proxy.request();

      RealSubject realSubject = new RealSubject();
      Proxy proxy1 = new Proxy(realSubject);
      proxy1.request();
  }

结果:

before
调用我
after
before
调用我
after

代理模式优缺点

优点:

  1. 职责清晰。真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事物。
  2. 高扩展性。具体主题角色是随时都会发生变化,只要实现它接口即可。我的代理类完全可以不做任何修改即可以使用。
  3. 智能化。

缺点:

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

扩展

1.普通代理

普通代理需要用户自己设置代理服务器的IP地址,用户必须知道代理的存在,然后才能访问。强制代理则是调用者直接调用真实角色,而不用关心代理是否存在,其代理的产生是由真实角色决定的。
普通代理客户端只能访问代理角色,不能访问真实角色。
修改:
代理类不需要传递进入被代理类的构造函数,同时,被代理类构造参数传入实现类。
接口:

public interface CommonSubject {
    void doSomething();
}

实现类:

public class CommonRealSubject implements CommonSubject {
    public CommonRealSubject(CommonSubject subject) {
        if (null==subject)
            throw new NullPointerException("subject is null");
    }
    @Override
    public void doSomething() {
        System.out.println("common real subject");
    }
}

代理类

public class CommonProxy implements CommonSubject {

    private CommonRealSubject realSubject = null;

    public CommonProxy() {
        realSubject = new CommonRealSubject(this);
    }
    @Override
    public void doSomething() {
        this.realSubject.doSomething();
    }
}

2.强制代理

强制代理必须通过真实角色查找到代理角色,否则不能访问。
接口:

public interface Player {
    void doSomething();
    // 获取类的指定代理,除了代理外,谁都不能访问。
    Player getProxy();
}

代理类:

public class PlayerProxy implements Player {
    private Player player = null;

    public PlayerProxy(Player player) {
        this.player = player;
    }
    @Override
    public void doSomething() {
        this.player.doSomething();
    }
    @Override
    public Player getProxy() {
        return this;
    }
}

被代理类:

public class RealPlayer implements Player{

    private Player player = null;

    @Override
    public void doSomething() {
        if (this.isProxy()){
            System.out.println("real player");
        }else {
            System.out.println("请使用代理");
        }
    }
    @Override
    public Player getProxy() {
        this.player = new PlayerProxy(this);
        return this.player;
    }
    private boolean isProxy(){
        if (null==player){
            return false;
        }
        return true;
    }
}

3.动态代理

动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。相对来说,自己写代理类的方式就是静态代理。
实现InvocationHandler接口。
代码:

public class PlayerIH implements InvocationHandler {
    // 被代理者
    Class cls = null;
    // 被代理者的实例
    Object obj = null;
    // 我要代理谁
    public PlayerIH(Object obj) {
        this.obj = obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(this.obj,args);
        if (method.getName().equalsIgnoreCase("login")){
            System.out.println("登录");
        }
        return result;
    }
}

猜你喜欢

转载自blog.csdn.net/dulei17816/article/details/80607923
今日推荐