代理模式(Proxy)

代理模式分为2种

 

其实就是实现一个代理类,来代理你所需要代理的类,访问的时候,通过访问代理类,来达到一定的效果

 

举个例子:

 

权限:有一个系统有很多权限,比如说只有管理员有增加的功能.用户访问到DAO的saveMessage方法

 

这个其实就是真正需要的保存方法,但是只有管理员才有权限

 

public class DbMessage implements Message{
...

public void saveMessage(String name) throws ForumAlreadyExistsException {

  this.name = name;
  //这里真正将新名称保存到数据库中 
  saveToDb();

}



}

 

怎么办了,创建一个代理类

public class MessageProxy implements Message{

private DbMessage dbMessage; 
private UserBean user;

public ForumProxy(DbMessage dbMessage, UserBean user)
{
this.dbMessage= dbMessage;
this.user= user;
}

.....

public void saveMessage(String name) throws Exception
{
  //只有是系统或论坛管理者才可以修改名称
  if (user.getRight.equal("***")) {
    forum.saveMessage(name);
  }
  else {
    throw new Exception();
  }
}


}

 利用代理类来实现权限的判断,Jive论坛系统的权限好象采用的代理模式,不过如果不是很了解的人,用起来可能会为了使用

 

代理模式而写代理模式,这样就违背了原来的意愿,只有写了一定多的代码的人才能炉火纯青的写.我只能表面理解.

 

1:静态代理.静态代理代理和被代理对象在代理之前是确定的。他们都实现相同的接口或者继承相同的抽象类。

 

上面的权限采用的也是静态代理

 

贴一些网上面比较有说明性的代码

 

Subject.java

 

/**
 * 抽象角色
 */
public abstract class Subject {
    abstract public void request();
}

 

RealSubject.java

 

/**
 * 真实角色:实现了Subject的request()方法
 */
public class RealSubject extends Subject {

    public RealSubject() {
    }

    public void request() {
        System.out.println("真实角色的请求方法RealSubject.request()被调用!");
    }
}

 

ProxySubject.java

 

/**
 * 代理角色
 */
public class ProxySubject extends Subject {
    private RealSubject realSubject; // 以真实角色作为代理角色的属性

    public ProxySubject() {
    }

    // 该方法封装了真实对象的request方法
    public void request() {
        preRequest();               //代理前执行的操作
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        realSubject.request();     // 此处执行真实对象的request方法
        postRequest();              //代理后执行的操作
    }

    private void preRequest() {
        // something you want to do before requesting
        System.out.println("代理前执行的操作ProxySubject.preRequest()!");
    }

    private void postRequest() {
        // something you want to do after requesting
        System.out.println("代理后执行的操作ProxySubject.postRequest()!");
    }
}

 

Client.java

 

/**
 * 客户端调用
 */
public class Client {
    public static void main(String[] args) {
        Subject sub = new ProxySubject();
        sub.request();
    }
}

 

这就是静态代理,通过访问代理类,来实现想要的方法,

 

客户实际需要调用的是RealSubject类的request()方法,现在用ProxySubject来代理 RealSubject类,同样达

 

到目的,同时还封装了其他方法(preRequest(),postRequest()),可以处理一些其他问题。

 
另外,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是
实际使用时,一个真实角色必须对应一个 代理角色,如果大量使用会导致类的急剧膨胀.

 

2:动态代理

 

如果事先并不知道真实角色,该如何使用代理,这就是动态代理所要解决的问题.

 

以下引用

 

Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:
 
(1)Interface InvocationHandler:该接口中仅定义了一个方法
public object invoke(Object obj,Method method, Object[] args)
在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数
数组。 这个抽象方法在代理类中动态实现。
 
(2)Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容
动态代理类
protected Proxy(InvocationHandler h):构造函数,用于给内部的h赋值。
 
static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载
器,interfaces是真实类所拥有的全部接口的数组。
 
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理
类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)
动态代理类
 
所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该
class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然,这个
Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接
管实际的工作
 
在使用动态代理类时,我们必须实现InvocationHandler接口。

 

底下的例子和上面共用同个subject接口,

 

动态代理类DynamicSubject.java

/**
 * 代理处理器
 *
 * 该代理类的内部属性为Object类,实际使用时通过该类的构造函数DynamicSubject(Object obj)对其赋值;
 * 此外,在该类还实现了invoke方法,该方法中的 method.invoke(sub,args);
 * 其实就是调用被代理对象的将要被执行的方法,方法参数sub是实际的被代理对象,
 * args为执行被代理对象相应操作所需的参数。
 * 通过动态代理类,我们可以在调用之前或之后执行一些相关操作
 */

public class DynamicSubject implements InvocationHandler {
    private Object sub;       //被代理对象

    public DynamicSubject() {
    }

    /**
     * 构造方法,并初始化被代理对象
     * @param obj 是被代理的对象
     */
    public DynamicSubject(Object obj) {
        sub = obj;
    }

    /**
     *
     * @param proxy  指代理类
     * @param method 被代理的方法
     * @param args   被代理的方法所需要的参数数组
     * @return  在代理实例上处理方法调用并返回结果。
     * @throws Throwable
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理前执行的操作!");
        method.invoke(sub, args);
        System.out.println("代理后执行的操作!");
        return null;
    }

 

client.java

/**
 * 客户端
 */
public class Client {
    static public void main(String[] args) throws Throwable {

        RealSubject rs = new RealSubject();     // 在这里指定被代理类
        //通过被代理类对象声明一个代理类对象
        InvocationHandler dynamicSubject = new DynamicSubject(rs);
        Class<?> cls = rs.getClass();

        // 以下是一次性生成代理类实例:
        // 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
        Subject subject = (Subject) Proxy.newProxyInstance(
                cls.getClassLoader(),           //定义代理类的类加载器
                cls.getInterfaces(),            //代理类要实现的接口列表
                dynamicSubject);                //指派方法调用的调用处理程序:InvocationHandler对象

        subject.request();      //调用代理处理器上的方法
    }
}

 

上面用动态代理来代理了静态代理,在运行时生成Class,在生成时候给他一组接口,然后这个class就宣称实现了这些接口

 

上面的例子实现代理了自己写的类,其实动态代理可以代理已有的类,例如vector

 

public class VectorProxy implements InvocationHandler {
    private Object proxyobj;

    public VectorProxy(Object obj) {
        proxyobj = obj;
    }

    public static Object factory(Object obj) {
        Class<?> cls = obj.getClass();

        return Proxy.newProxyInstance(cls.getClassLoader(),
                cls.getInterfaces(), new VectorProxy(obj));
    }

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("before calling " + method);

        if (args != null) {
            for (int i = 0; i < args.length; i++) {
                System.out.println(args[i] + "");
            }
        }
        Object object = method.invoke(proxyobj, args);

        System.out.println("after calling " + method);
        return object;
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        List<String> v = (List<String>) factory(new Vector<String>(10));

        v.add("New");
        v.add("York");
        System.out.println(v);

        v.remove(0);
        System.out.println(v);
    }
}

 

当做个笔记,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值