代理模式中有静态代理和动态代理之分,两者有何不同呢,用以下例子说明:
// 定义接口
public interface IShape {
public void calc();
}
// 实现类
public class Circle implements IShape {
public void calc() {
System.out.println("calc : circle");
}
}
// 静态代理类
class StaticProxy implements IShape{
private IShape shape = null;
public StaticProxy(IShape shape) {
this.shape = shape;
}
public void calc() {
before();
shape.calc();
after();
}
public void before() {
System.out.println("before");
}
public void after() {
System.out.println("after");
}
}
//
客户端类
public class TestStaticProxy {
public static void main(String[] args) {
new TestStaticProxy().doit();
}
public void doit() {
StaticProxy sp = new StaticProxy(new Circle());
sp.calc();
}
}
运行客户端类,输出如下:
before
calc : circle
after
若在接口 IShape 中添加新方法,如
public interface IShape {
……
public void transform();
}
则实现类也将添加 transform() 方法的实现
public class Circle implements IShape {
……
public void transform() {
System.out.println("Circle->Triangle");
}
}
此时若客户端类调用transform()新方法
sp = new StaticProxy( new Circle() );
sp.transform();
则必须去修改 StaticProxy 类,如下:
class StaticProxy implements IShape{
……
public void transform() {
System.out.println("before");
shape.transform();
System.out.println("after");
}
}
若使用动态代理,情况就不同了,如下:
public class TestDynamicProxy {
public static void main(String[] args) {
IShape s = new Circle();
// 运行时动态创建代理类
Class<?> clazz = Proxy.getProxyClass(IShape.class.getClassLoader(), new Class[]{IShape.class});
try{
Constructor<?> constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
// 实例化一个代理对象
IShape shape = (IShape)constructor.newInstance(new Handler(new Circle()));
shape.calc();
// 调用新方法
shape.transform();
}catch(Exception e) {
e.printStackTrace();
}
}
}
class Handler implements InvocationHandler {
private IShape shape = null;
public Handler(IShape shape) {
this.shape = shape;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = method.invoke(shape, args);
System.out.println("after");
return result;
}
}
可见,当在客户端类中调用接口 IShape 中添加的新方法时,可以在客户端类中直接调用,而不影响到其他代码,若使用静态代理,则必须在修改静态代理类后方可在客户端调用