WHWW之代理模式(1)-静态代理

What:什么是静态代理?

代理就是用于通过对真实对象的封装,对原有业务逻辑的扩充,来实现扩展性。。比如持有二方包的某个类,并调用了其中的某些方法。然后出于某种原因,比如记录日志、打印方法执行时间,但是又不好将这些逻辑写入二方包的方法里。所以可以创建一个代理类实现和二方方法相同的方法,通过让代理类持有真实对象,然后在原代码中调用代理类方法,来达到添加我们需要业务逻辑的目的。由于在程序运行前代理类就已经获得目标对象了,所以把这类称为静态代理。

How:怎么实现静态代理呢?

静态代理的类图:

WHWW之代理模式(1)-静态代理

根据类图我们可以实现静态代理

/**
 * 抽象角色接口
 */
public interface Hello {

    /**
     * 打招呼
     */
   public void sayHello();
}
/**
 * 目标对象角色类
 */
public class RealHello implements Hello {
    /**
     * 实现接口的方法
     */
    @Override
    public void sayHello() {
        System.out.println("你好");
    }
}
/**
 * 代理对象角色类
 */
public class ProxyHello implements Hello {

    private Hello realHello;

    public ProxyHello(Hello realHello) {
        this.realHello = realHello;
    }

    /**
     * 实现接口的方法
     */
    @Override
    public void sayHello() {
        before();
       realHello.sayHello();
        after();
    }

    /**
     * 在实现方法前可以做的事情
     */
    public  void  before(){
        System.out.println("摘下耳机");
    }

    /**
     * 在实现方法后做的事情
     */
    public void after(){
        System.out.println("戴上耳机");
    }
}
/**
 * 客户端,实现代理模式
 */
public class ProxyTest {

    public static void main(String[] args) {
        System.out.println("没有代理的,目标对象自己实现:");
        Hello hello = new RealHello();
        hello.sayHello();
        System.out.println("=========================");
        System.out.println("代理对象实现的:");
        ProxyHello proxyHello = new ProxyHello(hello);
        proxyHello.sayHello();


    }
}

控制台输出:

没有代理的,目标对象自己实现:

你好
=========================
代理对象实现的:
摘下耳机
你好
戴上耳机

Why:为什么要使用静态代理

首先我们可以想一下,如果不用代理模式,那么我们要实现sayHello()方法之前执行某些方法或者之后执行某些方法,就必须在目标对象角色把代码写死。目标对象类图就变为这样了:

WHWW之代理模式(1)-静态代理

也许我们想,这样写也没什么不好啊,而且写个代理类还增加了类的数量,维护工作不也增加了吗?但我们想想如果有大量的类要加类似代码,都这样写的话,那么我们工作量比较大,而且这样的类不容易重构,而且如果我们又要增加其他功能时,又得修改其他所有的类,所有扩展性比较低。所以这时候我们应该想到代理类,我们可以在不改变原目标类的情况下,为目标对象类增加额外的功能,如果我们要为目标对象再增加其他功能,我们可以又写另一个代理类就好了。这样代码的理解,重构,扩展性都比这样写死的代码好多了。

Where:哪些地方使用过静态代理?

    保存用户功能可以使用静态代理实现

静态代理的优缺点:

优点:可以在不修改目标对象的前提下扩展目标对象的功能。

缺点:

  1. 冗余。由于代理对象要实现与目标对象一致的接口,会产生过多的代理类。
  2. 不易维护。一旦接口增加方法,目标对象与代理对象都要进行修改。

注:静态代理方式需要代理对象和目标对象实现一样的接口。