您的位置:首页 > 编程语言 > Java开发

我的设计模式学习之路3(动态代理)

2013-05-05 22:21 609 查看

  代理模式(Proxy)

 

1.静态代理

  角色:

  抽象主题角色:声明了代理角色和真实角色的共同接口

  代理角色:代理角色内部含有对真实角色的引用,通常在将客户端调整用传弟它们真实角色之前或者之后,都要执行某个操作

  真实角色:定了代理角色所代表的真实对象

  类图:

 


  下面是我的写的一个例子:

  首先是抽象主题角色:

 

package com.design.proxy;

public interface Runable
{
public void move();

}
   代理角色,这里有两个:
package com.design.proxy;

public class TankTimeProxy implements Runable
{
private Runable t;

public TankTimeProxy(Runable t)
{
this.t=t;
}

@Override
public void move()
{
System.out.println("time is start ........");
t.move();

}

}

package com.design.proxy;

public class TankLogProxy implements Runable
{
private Runable t;

public TankLogProxy(Runable t)
{
this.t=t;
}

@Override
public void move()
{
System.out.println("Log is record");
t.move();
}

}


 真实角色:

public class Tank implements Runable
{
@Override
public void move()
{
long start=System.currentTimeMillis();

System.out.println("tank is move..");
try
{
Thread.sleep(new Random().nextInt(10000));
} catch (InterruptedException e)
{
e.printStackTrace();
}

long end=System.currentTimeMillis();

System.out.println("time:"+(end-start));
}

}
 

  最后是测试类:

package com.design.proxy;

public class Client
{
public static void main(String[] args)
{
Tank tank = new Tank();

TankTimeProxy ttp=new TankTimeProxy(tank);

TankLogProxy tlp = new TankLogProxy(ttp);

tlp.move();

}

}


输出结果:

Log is record

time is start ........

tank is move..

time:1728

   测试类可以动态地改变,相应由不同的代理角色来完成不同的功能,这是简单的代理,缺点就是不太灵活。

 2.动态代理

  动态代理需要实现InvocationHandler这个接口,并且@Ovrride里面的invoke()方法,让InvocationHandler接口来帮我们代理,代理类需要有个静态工厂的方法,下面是我的一个例子:

  接口:

package com.proxy2;

public interface UserManager
{
public void save();
}


 接口的实现:

package com.proxy2;

public class UserManagerImpl implements UserManager
{
@Override
public void save()
{
System.out.println("用户保存中...");
}
}
  两个代理类:

package com.proxy2;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class UserLogProxy implements InvocationHandler
{
private Object target;

public UserLogProxy(Object target)
{
this.target=target;
}

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

return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new UserLogProxy(obj));
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
System.out.println("开始写日记...");

Object o=method.invoke(target, args);

System.out.println("记录完毕....");

return  o;
}
}

package com.proxy2;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class UserInvokedProxy implements InvocationHandler
{
private Object target;

public UserInvokedProxy(Object target)
{
this.target=target;
}

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

return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new UserInvokedProxy(obj));
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
System.out.println("类加载...");

Object o=method.invoke(target, args);

return o;
}
}


 测试类:

package com.proxy2;

public class Client
{
public static void main(String[] args)
{
UserManager user = new UserManagerImpl();

UserManager user1=(UserManager)UserLogProxy.factory(user);

UserManager user2=(UserManager)UserInvokedProxy.factory(user1);

user2.save();
}
}


 测试的结果:

类加载中...

开始写日记...

用户保存中...

记录完毕....

   这样就可以实现了动态代理,而且是一个对象对应多个代理。动态代理的应用还是很广泛的,比如Spring的AOP等,感谢《JAVA与设计模式》这本书,让我知道了多个代理的写法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式 java编程