学习设计模式 - 代理模式

2019-07-09

学习设计模式 - 代理模式

学习设计模式 - 代理模式

一丶定义

   代理模式为另一个对象提供替身或者占位符以控制对这个对象访问, 被代理的对象可以是远程的对象、创建开销大的对象、需要安全控制的对象

 

二丶理解

   2.1) 当一个对象除了处理真正的业务逻辑之外, 还需要增加额外的处理,如事务,打印日志等等, 如果将这些额外逻辑放到原对象中,会造成职责不清晰.
          这时可以使用代理对象代理该对象, 代理对象实现额外逻辑, 真正的业务逻辑则委托给被代理对象处理.这样可以使得职责清晰.


     2.2) 为另一个对象提供一个替身或占位符以控制对这个对象的访问.这也是代理模式和装饰者模式之间的重要区别
          当一个对象是大对象或者消耗资源的对象, 为提高系统性能, 可以使用代理对象暂时替代该对象, 到真正需要的时候才生成该对象.
          当权限不够时,可以使用代理对象限制对该对象的访问.

 

 

三丶静态代理

  技术图片

 

 

  a. 主题

public interface Subject {
    void request();
}

 

  b. 真实主题

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("真正业务逻辑...");
    }
}

 

   c. 代理

public class Proxy implements Subject {

    private Subject subject;

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

    @Override
    public void request() {
        System.out.println("增加事务...");
        subject.request();
    }
}

 

  d. 场景类

/**
 * 静态代理
 *
 *  缺点:
 *      相同的代理方法,却要写多个代理类
 * @author TimFruit
 * @date 19-5-25 下午10:15
 */
public class Client {

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

        Proxy2 proxy2=new Proxy2(new RealSubject2());
        proxy2.request();
    }

}

 

  运行结果为:

增加事务...
真正业务逻辑...
增加事务...
真正的业务处理2...

 

  还有类似的代码Proxy2没有贴出来, 完整代码可以点此查看

 

四丶JDK动态代理

  由上面代码可知, 使用静态代理需要为每个"被代理的类", 实现代理类, 当代理类实现方法相同时, 将会产生很多繁琐重复的代码, 因此有了动态代理, 动态代理一般有两种常用的实现, 一种是jdk动态代理, 一种是cglib动态代理. 这里展示的是jdk动态代理.

 

/**
 * 实现jdk自带的接口
 * 写一个较为通用的"切面"类
 * @author TimFruit
 * @date 19-5-26 上午10:57
 */
public class ProxyInvocationHandler implements InvocationHandler {

    private Object target;

    public ProxyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("增加事务...");
        return method.invoke(target, args);
    }
}

  

  场景类:

/**
 * JDK动态代理
 *  <p>
 *      好处是写一个较为通用的"切面"类就可以了, 动态生成对应的代理类, 减少代码量
 *
 * @author TimFruit
 * @date 19-5-26 上午11:00
 */
public class Client {
    public static void main(String[] args) {

        RealSubject subject=new RealSubject();
        InvocationHandler proxyInvocationHandler=new ProxyInvocationHandler(subject);
        //动态生成代理类
        Subject subjectProxy= (Subject) Proxy.newProxyInstance(Client.class.getClassLoader(), new Class[]{Subject.class}, proxyInvocationHandler);
        subjectProxy.request();



        RealSubject2 subject2=new RealSubject2();
        InvocationHandler proxyInvocationHandler2=new ProxyInvocationHandler(subject2);
        // 动态生成代理类
        Subject2 subjectProxy2= (Subject2) Proxy.newProxyInstance(RealSubject2.class.getClassLoader(), new Class[]{Subject2.class}, proxyInvocationHandler2);
        subjectProxy2.request();
    }
}

 

   运行结果为:

增加事务...
真正业务逻辑...
增加事务...
真正的业务处理2...

 

   完整代码点此查看

 

 

 学习资料:

  <Head First 设计模式>

  <设计模式之禅>

 

 

学习设计模式 - 代理模式

学习设计模式 - 代理模式

原文地址:https://www.cnblogs.com/timfruit/p/11154804.html