设计模式学习笔记—代理模式

代理模式(Proxy Pattern)

如果想在一个类中大多数方法之前或之后统一做一些事,那就用代理模式吧。

代理模式的用途也不少,比如大多数 service 中的方法之前都要判断一下用户是否登录,如果没有登录肯定就不能让这个用户进行操作,或者 dao 中每次都要打开然后关闭一些东西什么的,这样就可以把这些公共的部分提取出来,比较著名的 spring 面向切面编程(AOP) 就是代理模式的一种实现,虽然我已经忘了 AOP 怎么写的了。 T T
正常情况下的代理模式(所以肯定有非正常的 = =),要与被代理的类继承同一个接口,就像这样

public interface BookService {
    List<Book> getByUserId(int userId);
    void create(Book book, int userId);
    void update(Book book);
    void delete(Book book);
}
public class BookServiceImpl implements BookService {

    @Override
    public List<Book> getByUserId(int userId) {
        System.out.println("get");
        return new ArrayList<Book>();
    }

    @Override
    public void create(Book book, int userId) {
        System.out.println("create");
    }

    @Override
    public void update(Book book) {
        System.out.println("update");
    }

    @Override
    public void delete(Book book) {
        System.out.println("delete");
    }

}
public class ServiceProxy implements BookService {
    private BookService mBookService;

    public ServiceProxy(BookService bookService) {
        mBookService = bookService;
    }

    @Override
    public List<Book> getByUserId(int userId) {
        this.before();
        List<Book> books =  mBookService.getByUserId(userId);
        this.after();
        return books;
    }

    @Override
    public void create(Book book, int userId) {
        this.before();
        mBookService.create(book, userId);
        this.after();
    }

    @Override
    public void update(Book book) {
        this.before();
        mBookService.update(book);
        this.after();
    }

    @Override
    public void delete(Book book) {
        mBookService.delete(book);
    }

    private void before() {
        System.out.println("before");
    }

    private void after() {
        System.out.println("after");
    }

}

然而这些代码并没有什么实际的意义,话说 service 和 dao 的例子我已经用了好多个了,Because I think that the majority of people studied it in college.(然而我英语并不好 - -)
调用的时候会是这样

        BookService bookService = new ServiceProxy(new BookServiceImpl());
        bookService.create(new Book(), 1);
        bookService.delete(new Book());

看起来调用还不错,作为一个设计模式而言,不过不单单是这一个类需要这样的代理,可能程序中的每一个 service 都需要一个代理,虽然可以用工厂给封装起来,但是那么多的代理类基本上也是做的相同的工作,所以就有了动态代理。

public class ServiceProxy implements InvocationHandler {
    private Object mServiceObj = null;

    public ServiceProxy(Object serviceObj) {
        mServiceObj = serviceObj;
    }

    private void before() {
        System.out.println("before");
    }

    private void after() {
        System.out.println("after");
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 这就是为什么 service 中经常以这种规范进行命名的原因
        String[] limits = new String[] {"get", "create", "update"};
        boolean isAllow = false;
        String methodName = method.getName();
        for (String limit : limits) {
            if (methodName.startsWith(limit)) {
                isAllow = true;
            }
        }
        Object result = null;
        if (isAllow) {
            this.before();
        }
        // 这个就是需要执行的那个方法
        result = method.invoke(mServiceObj, args);
        if (isAllow) {
            this.after();
        }
        return result;
    }
}

代理类的话改动比较大,实际上就多了几行对于方法名限定,如果简单的话完全可以这么写

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        this.before();
        // 这个就是需要执行的那个方法
        result = method.invoke(mServiceObj, args);
        this.after();
        return result;
    }

然后,我们需要一个工厂,不然调用部分的代码会很难看

public class ServiceFactory {
    public static Object getBean(String name) {
        if ("bookService".equals(name)) {
            BookService service = new BookServiceImpl();
            ServiceProxy proxy = new ServiceProxy(service);
            return Proxy.newProxyInstance(service.getClass().getClassLoader(),
                    service.getClass().getInterfaces(), proxy);
        }
        return null;
    }
}

嘛,工厂的责任就是负责组装好组件之间的关系,最后的调用会是这个样子的

        BookService bookService = (BookService) ServiceFactory.getBean("bookService");
        bookService.create(new Book(), 1);
        bookService.delete(new Book());

这样看起来就好多了。
PS:如果将代理类作为一个模板方法,before after 之类的延迟到子类去实现,工厂负责读取 xml,反射创建对象,这样的话应该也能有点框架的意思了吧。

The end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值