代理模式

2017-03-30  本文已影响0人  yl1415

写在前面

看dubbo等各种大型框架源码时,发现其中都大量利用到代理模式。按照之前自己对代理模式肤浅的理解,仅仅是对实际要调用的对象包装了一层,可是这么做的原因或者说好处到底是啥,一直不是很清楚。同时注意到Java中有动态代理技术,这边文章顺到来梳理这些问题。

模式定义

代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。

定义总是很抽象。代理模式不仅为另一个对象提供替身,同时还可以控制访问,几种常见控制访问的方式如下

代理模式类图

代码实战

1. 远程代理

Java RMI 技术。RMI提供了客户端辅助对象sub(桩),服务端辅助对象skeleton(骨架),不用亲自写任何网络或IO代码。

2. 虚拟代理

3. 保护代理

Java在java.lang.reflect包中有对代理的支持,该包可以在运行时动态的创建代理类,实现一个或多个接口,并将方法调用转发到所指定的类。因为实际的代理类是在运行时创建的,故称该技术为动态代理

在本节,我们利用Java的动态代理技术创建保护代理,类图如下:

Java动态代理类图

定义接口

public interface PersonBean {
    String getName();
    String getGender();
    String getInterests();
    int getHotOrNotRating();

    void setName(String name);
    void setGender(String gender);
    void setInterests(String interests);
    void setHotOrNotRating(int rating);
}

实现接口

public class PersonBeanImpl implements PersonBean {
    String name;
    String gender;
    String interests;
    int rating;
    int ratingCount = 0;

    public PersonBeanImpl(String name) {
        this.name = name;
    }

    public int getHotOrNotRating() {
        if (ratingCount == 0) return 0;
        return rating / ratingCount;
    }

    public void setHotOrNotRating(int rating) {
        this.rating = rating;
        ratingCount++;
    }
}

创建InvocationHandler

public class OwnerInvocationHandler implements InvocationHandler {
    PersonBean person;

    public OwnerInvocationHandler(PersonBean person) {
        this.person = person;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException {
        try {
            if (method.getName().startsWith("get")) {
                return method.invoke(person, args);
            } else if (method.getName().equals("setHotOrNotRating")) {
               // 权限控制
                throw new IllegalAccessException();
            } else if (method.getName().startsWith("set")) {
                return method.invoke(person, args);
            }
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }
}

创建Proxy对象

    PersonBean getOwnerProxy(PersonBean person) {
        return (PersonBean)Proxy.newProxyInstance(
                person.getClass().getClassLoader(),
                person.getClass().getInterfaces(),
                new OwnerInvocationHandler(person));
    }

测试代码(测试权限控制)

        PersonBean joe = new PersonBeanImpl("Joe Javabean");

        PersonBean ownerProxy = getOwnerProxy(joe);
        System.out.println("Name is " + ownerProxy.getName());
        ownerProxy.setInterests("swimming");
        try {
            ownerProxy.setHotOrNotRating(10);
        } catch (Exception e) {
            System.out.println("cat not set rating from owner proxy");
        }
        System.out.println("rating is " + ownerProxy.getHotOrNotRating());

小结

代理模式 要做的:控制和管理访问。

代理模式类似装饰者模式:前者控制访问,后者为对象加上行为。Java内置有代理支持,即动态代理

上一篇 下一篇

猜你喜欢

热点阅读