目录:
- 概述
- 观察者模式
- 代理模式
概述:
spring系列中使用了大量的设计模式,而最常见的便是这观察者、代理模式,所以在讲解SpringCloud之前我们先学习下这两个最常见的设计模式。
观察者模式:
java实现了自己的观察者模式 >>> java.util.Observable;
1、public synchronized void addObserver(Observer o);添加一个观察者
2、public synchronized void deleteObserver(Observer o);删除一个观察者
3、protected synchronized void setChanged();修改通知标记,使得观察者观察的对象发生变化时能记得得知
4、public void notifyObservers(Object arg) ;通知观察者,被观察这已发生变化
1 public class ObserverDemo extends Observable { 2 3 /** 4 * 通知观察者被观察者已发生变化 5 */ 6 public void notifyObserver() { 7 // 设置变化状态为true >>> 被观察者已发生变化 8 this.setChanged(); 9 // 将这一变化通知观察者 10 this.notifyObservers(); 11 } 12 13 public static void main(String[] args) { 14 testAddObserver(); 15 testDeleteObserver(); 16 } 17 18 private static void testAddObserver() { 19 ObserverDemo observerDemo = new ObserverDemo(); 20 observerDemo.addObserver((o, arg) -> System.err.println("服务列表发生变化1")); 21 observerDemo.notifyObserver(); 22 } 23 24 private static void testDeleteObserver() { 25 ObserverDemo observerDemo = new ObserverDemo(); 26 Observer observer = (o, arg) -> System.err.println("服务列表发生变化2"); 27 28 observerDemo.addObserver(observer); 29 observerDemo.notifyObserver(); 30 observerDemo.deleteObserver(observer); 31 observerDemo.notifyObserver(); 32 } 33 }
代理模式:
1、静态代理
代理就是将除了自己本身需要做的核心业务外的任务交给代理人来做,如明星将接广告等事情交给经纪人。
1 public interface Agent { 2 3 /** 4 * 拍广告 5 */ 6 void advertising(); 7 }
1 public class Celebrity implements Agent { 2 3 @Override 4 public void advertising() { 5 System.err.println("Celebrity拍广告"); 6 } 7 }
1 public class Celebrity2 implements Agent { 2 3 @Override 4 public void advertising() { 5 System.err.println("Celebrity2拍广告"); 6 } 7 }
1 public class ProxyDemo implements Agent { 2 3 private Agent agent; 4 5 public ProxyDemo(Agent agent) { 6 this.agent = agent; 7 } 8 9 @Override 10 public void advertising() { 11 before(); 12 agent.advertising(); 13 after(); 14 } 15 16 private void after() { 17 System.err.println("after"); 18 } 19 20 private void before() { 21 System.err.println("before"); 22 } 23 } 24 25 class ProxyClient { 26 27 public static void main(String[] args) { 28 Agent agent = new ProxyDemo(new Celebrity()); 29 agent.advertising(); 30 31 System.out.println("----------------------------"); 32 33 Agent agent2 = new ProxyDemo(new Celebrity2()); 34 agent2.advertising(); 35 } 36 }
静态代理的缺点是如果代理对象新代理了一个行为,那么委托对象也需要将新的代理行为重实现一遍,这样非常繁琐且重复。
为什么说静态代理繁琐呢,我们来增加一个行为。
1 public interface Agent { 2 /** 3 * 拍广告 4 */ 5 void advertising(); 6 7 /** 8 * 集资 9 */ 10 void collectMoney(); 11 }
然后我们修改一下Celebrity、Celebrity2
1 public class Celebrity implements Agent { 2 3 @Override 4 public void advertising() { 5 System.err.println("Celebrity拍广告"); 6 } 7 8 @Override 9 public void collectMoney() { 10 System.err.println("Celebrity集资"); 11 } 12 }
1 public class Celebrity2 implements Agent { 2 3 @Override 4 public void advertising() { 5 System.err.println("Celebrity2拍广告"); 6 } 7 8 @Override 9 public void collectMoney() { 10 System.err.println("Celebrity2集资"); 11 } 12 }
然后我们看看修改后的ProxyDemo
1 public class ProxyDemo implements Agent { 2 3 private Agent agent; 4 5 public ProxyDemo(Agent agent) { 6 this.agent = agent; 7 } 8 9 @Override 10 public void advertising() { 11 before();
12 agent.advertising(); 13 after(); 14 } 15 16 @Override 17 public void collectMoney() { 18 before();
19 agent.collectMoney(); 20 after();
21 } 22 23 private void after() { 24 System.err.println("after"); 25 } 26 27 private void before() { 28 System.err.println("before"); 29 } 30 } 31 32 class ProxyClient { 33 34 public static void main(String[] args) { 35 Agent agent = new ProxyDemo(new Celebrity()); 36 agent.advertising(); 37 agent.collectMoney(); 38 39 System.out.println("----------------------------"); 40 41 Agent agent2 = new ProxyDemo(new Celebrity2()); 42 agent2.advertising(); 43 agent2.collectMoney(); 44 } 45 }
我们发现仅仅增加一个行为委托类也要实现collectMoney,实现时不仅需要调用agent.collectMoney,还需要调用before和after是不是很麻烦,而接下来要讲的动态代理正是为了解决这一问题。
2、动态代理
动态代理的例子还是和静态代理一样,我们首先将委托类写好。
1 public class DynamicProxyDemo implements InvocationHandler { 2 3 private Object target; 4 5 public DynamicProxyDemo(Object target) { 6 this.target = target; 7 } 8 9 @Override 10 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 11 after(); 12 Object invoke = method.invoke(target, args); 13 before(); 14 return invoke; 15 } 16 17 private void after() { 18 System.err.println("after"); 19 } 20 21 private void before() { 22 System.err.println("before"); 23 } 24 25 public Object getProxy() { 26 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); 27 } 28 }
其中最重要的是InvocationHandler接口和getProxy方法。
此时我们再往Agent增加一个行为,Celebrity、Celebrity2省略
1 public interface Agent { 2 /** 3 * 拍广告 4 */ 5 void advertising(); 6 7 /** 8 * 集资 9 */ 10 void collectMoney(); 11 12 /** 13 * 安排行程 14 */ 15 void travelArrangements(); 16 }
然后我们发现,DynamicProxyDemo不需要再实现新的行为了,这都归功于InvocationHandler !!!∑(゚Д゚ノ)ノ
1 class DynamicProxyClient { 2 3 public static void main(String[] args) { 4 DynamicProxyDemo dynamic = new DynamicProxyDemo(new Celebrity()); 5 Agent agent = (Agent) dynamic.getProxy(); 6 agent.advertising(); 7 agent.collectMoney(); 8 agent.travelArrangements(); 9 } 10 }