下面我们来看客户端:  
Action action = (Action)ProxyAction.getInstance(new ViewAction());  
Action.doAction();  
    我们可以看到代理类对接口的依赖也转移到了客户端上,这样,代理类不依赖于某个接口。对于同样的代理类ProxyAction,我们也可以有如下的客户端调用:  
Engine engine = (Engine)ProxyAction.getInstance(new EngineImpl());  
Engine.execute();  
    只要engineImpl类实现了Engine接口,就可以像上面那样使用。  
    现在我们可以看到,动态代理的确是拥有相当的灵活性。但我们同时也看到了,这个代理类写起来比较麻烦,而且也差不多每次都写这样千篇一律的东西,只有委派前的动作和委派后的动作在不同的代理里有着不同,其他的东西都需要照写。如果这样的代理类写多了,也会有一些冗余代理。需要我们进一步优化,这里我们使用模板方法模式来对这个代理类进行优化,如下:  
public abstract class BaseProxy implements InvocationHandler {  
private Object obj;  
protected BaseProxy(Object obj)  
{  
       this.obj = obj;  
}  
public static Object getInstance(Object obj,InvocationHandler instance)  
{  
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),  
obj.getClass().getInterfaces(),instance);  
}  
 
public Object invoke(Object proxy, Method m, Object[] args)  
               throws Throwable {  
        // TODO Auto-generated method stub  
        Object result;  
 
       try {  
 
           System.out.println("before method " + m.getName());  
           this.doBegin();  
 
           result = m.invoke(obj, args);  
 
       } catch (InvocationTargetException e) {  
 
           throw e.getTargetException();  
 
       } catch (Exception e) {  
 
           throw new RuntimeException("unexpected invocation exception: "  
 
                  + e.getMessage());  
 
       } finally {  
 
           System.out.println("after method " + m.getName());  
           this.doAfter();  
 
       }  
 
       return result;  
 
 
}  
public abstract void doBegin();  
public abstract void doAfter();  
 
}  
    这样,代理的实现类只需要关注实现委派前的动作和委派后的动作就行,如下:  
public class ProxyImpl extends BaseProxy {  
protected ProxyImpl(Object o)  
{  
       super(o);  
}  
public static Object getInstance(Object foo)  
{  
        return getInstance(foo,new ProxyImpl(foo));  
}  
 
//委派前的动作  
public void doBegin() {  
        // TODO Auto-generated method stub  
       System.out.println("begin doing....haha");  
 
}  
 
//委派后的动作  
public void doAfter() {  
        // TODO Auto-generated method stub  
       System.out.println("after doing.....yeah");  
 
}  
 
}  
    从上面的代码,我们可以看出代理实现类的确是简单多了,只关注了委派前和委派后的动作,这是我们作为一个代理真正需要关心的。  
    至此,代理模式和动态代理已经告一段落。我们将动态代理引申一点说开去,来作为这篇文章的蛇足。  
    这个话题就是面向方面的编程,或者说AOP。我们看上面的ProxyImpl类,它的两个方法doBegin()和doAfter(),这是做核心动作之前和之后的两个截取段。正是这两个截取段,却是我们AOP的基础。在OOP里,doBegin(),核心动作,doAfter()这三个动作在多个类里始终在一起,但他们所要完成的逻辑却是不同的,如doBegin()可能做的是权限,在所有的类里它都做权限;而在每个类里核心动作却各不相同;doAfter()可能做的是日志,在所有的类里它都做日志。正是因为在所有的类里,doBegin()或doAfter()都做的是同样的逻辑,因此我们需要将它们提取出来,单独分析、设计和编码,这就是我们的AOP的思想。  
    这样说来,我们的动态代理就能作为实现AOP的基础了。好了,就说这么多,关于AOP技术,我们可以去关注关于这方面的知识。   
 
 
 |   
        
 
    
    
    
     
 
 |