设计模式之 代理模式上 静态代理

代理模式(Proxy Pattern),通过一个代理类,来支持原本想调用类的功能,并能在原有类的基础上,附加其他功能。也就是说我原本想调用A类,但是现在我改成调用B类,并且B类拥有完整的A的功能,对调用方依然可以拿到A的结果,而且还可以在调用前后附加其他功能,或者是修改结果。

但是为什么这么做呢?

通过代理类,可以在调用A类目标方法的前后,附加一些功能,比如在A类的business()方法前后记录日志、记录时间进行性能监控等。

这样就能让我们即拥有A的完整功能,又能扩展出其他我们需要的功能。

总结来说:代理模式将和业务不相关的功能,剥离出来,交给其他角儿来完成,从而使我们的业务类更专注与业务代码。

代理类分为静态代理和动态代理。

我们先来看看静态代理。

我们在demo中添加两个基于用户的方法,一个是用户登录,一个是模拟一个用户业务计算的方法。其中用户登录,我们让代理类除了登录以外,还附加日志记录功能,用户每次登录时都进行日志记录;另一个业务计算方法,我们让代理类另外完成性能监控功能。

1、建立抽象用户类

package com.my.study.design.proxy;

/**
 * www.itzhimei.com
 */
public interface IUser {

    void login(String userName,String pwd);

    void business() throws InterruptedException;
}

2、实现用户类

package com.my.study.design.proxy;
/**
 * www.itzhimei.com
 */
public class User implements IUser {
    @Override
    public void login(String userName,String pwd) {
        System.out.println("用户["+userName +"]登录.");
    }

    @Override
    public void business() throws InterruptedException {
        System.out.println("执行业务方法计算中....");
        Thread.sleep(500L);
        System.out.println("执行业务方法计算完成");
    }
}

3、定义代理类,代理类也实现抽象用户方法,让代理类看起来和用户类是一样的,具备相同能力。

package com.my.study.design.proxy;
/**
 * www.itzhimei.com
 */
public class Proxy implements IUser {

    private IUser user;
    public Proxy(IUser user) {
        this.user = user;
    }

    @Override
    public void login(String userName, String pwd) {
        //登录时进行日志打印
        System.out.println("用户["+userName +"]登录日志记录开始...");
        user.login(userName, pwd);
        System.out.println("用户["+userName +"]登录日志记录结束...");
    }

    @Override
    public void business() throws InterruptedException {
        long startTimestamp = System.currentTimeMillis();
        user.business();
        long endTimeStamp = System.currentTimeMillis();
        long t = endTimeStamp - startTimestamp;
        System.out.println("用户执行业务计算总用时:"+ t);
    }
}

在代理类中,持有了一个User对象,真正的用户业务,代理类会调用用户类来处理,代理类在调用用户类之前或之后附加其他功能。

4、测试

package com.my.study.design.proxy;
/**
 * www.itzhimei.com
 */
public class Client {

    public static void main(String[] args) throws InterruptedException {
        IUser user = new User();
        IUser proxy = new Proxy(user);
        proxy.login("张三","123");
        System.out.println("----------------------------------");
        proxy.business();
    }
}

输出:

用户[张三]登录日志记录开始...
用户类输出:用户[张三]登录.
代理类输出:用户[张三]登录日志记录结束...
----------------------------------
用户类输出:执行业务方法计算中....
用户类输出:执行业务方法计算完成
代理类输出:用户执行业务计算总用时:500

以上就是一个静态代理的完整实现。

类关系图: