举个例子,有一个对象Car,其有一个方法run(),现在我们需要知道车子跑了多久,OK,我们首先可能会想到使用继承来监听此方法,就知道车子跑了多久了。
1 package com.learn.www; 2 3 public interface Runable { 4 void run(); 5 }
1 package com.learn.www; 2 3 import java.util.Random; 4 5 public class Car implements Runable { 6 7 @Override 8 public void run() { 9 System.out.println("Car Running...."); 10 try { 11 Thread.sleep(new Random().nextInt(1000)); 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 } 15 } 16 17 }
1 package com.learn.www; 2 3 public class CarChild extends Car { 4 5 @Override 6 public void run() { 7 long start = System.currentTimeMillis(); 8 super.run(); 9 long end = System.currentTimeMillis(); 10 System.out.println("run time:" + (end -start)); 11 } 12 13 }
1 package com.learn.www; 2 /** 3 * 4 * @author LingJian 5 * 6 */ 7 public class Test { 8 9 public static void main(String[] args) { 10 Runable c = new CarChild(); 11 c.run(); 12 } 13 14 }
但是很显然,如果我们又想知道这个监听类的方法运行了多久,我们继续使用继承的话就会出现类爆炸的情况,这肯定不是我们期望的。
那么我们可以再试试下聚合,把Car分给一个类来监听。
1 package com.learn.www; 2 3 public class CarTimeProxy implements Runable { 4 private Runable r; 5 6 7 8 public CarTimeProxy(Runable r) { 9 super(); 10 this.r = r; 11 } 12 13 14 15 @Override 16 public void run() { 17 long start = System.currentTimeMillis(); 18 r.run(); 19 long end = System.currentTimeMillis(); 20 System.out.println("run time:" + (end -start)); 21 } 22 23 }
1 package com.learn.www; 2 /** 3 * 4 * @author LingJian 5 * 6 */ 7 public class Test { 8 9 public static void main(String[] args) { 10 Runable c = new Car(); 11 Runable proxy = new CarTimeProxy(c); 12 proxy.run(); 13 } 14 15 }
明显这样的做法要比继承好,而这种做法用一个设计模式的术语来形容就是代理模式。
代理模式按不同的目的有很多不同的命名,虚拟代理、远程代理、智能引用代理和保护代理是最常见的代理模式,根据代理的变化方式又可以分为静态代理和动态代理,个人认为智能引用代理和保护代理属于动态代理,而Spring的AOP就是动态代理的一种非常广泛的应用,如事务、日志。