代理模式(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与设计模式》这本书,让我知道了多个代理的写法。