观察者模式
一种行为型模式,当对象间存在一对多的对应关系时,并且有需要将通知发送给所有的依赖对象,这时可以采用观察者模式。
- 优点
- 1、耦合度低
- 2、有一套相应的触发机制
- 缺点
- 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
代码展示
- 定义接口
/** *观察者 */ public interface Observer { //处理消息 public void handle(String message); } /** * 观察者模式的主题类 */ public interface Subject { //通知所有的观察者 public void nodifyObservers(String message); //注册观察者 public void attach(Observer ob); }
- 编写实现
/** * 观察者实现 */ public class DefaultObserver implements Observer { @Override public void handle(String message) { System.out.println(message + ": " + Thread.currentThread().getName()); } } /** * 主题类 */ public class DefaultSubject implements Subject { private List<Observer> observers = new ArrayList<>(); @Override public void nodifyObservers(String message) { observers.forEach((o) -> o.handle(message)); } @Override public void attach(Observer ob) { this.observers.add(ob); } }
- 代码测试
@Test public void test_observer(){ Subject subject = new DefaultSubject(); subject.attach(new DefaultObserver()); subject.attach(new DefaultObserver()); subject.attach(new DefaultObserver()); subject.attach(new DefaultObserver()); subject.attach(new DefaultObserver()); subject.nodifyObservers("observer pattern test"); }
- 测试结果
observer pattern test: main observer pattern test: main observer pattern test: main observer pattern test: main observer pattern test: main
- 改进措施
以上的notifyObservers方法通知所有的观察者时,采用的同步的方式处理的,上文已说到,此种同步方式可能会导致系统性能问题,或者有一个出现问题时,会导致其他的观察者通知不到。那么,我们做如下改造:- Code
/** * 异步处理主题类 */ public class AsyncSubject implements Subject { private List<Observer> observers = new ArrayList<>(); ExecutorService service = Executors.newFixedThreadPool(10); @Override public void nodifyObservers(String message) { // for (Observer ob : observers) { // service.submit(new Runnable() { // @Override // public void run() { // ob.handle(message); // } // }); // } observers.forEach((ob) ->{service.submit(() -> ob.handle(message));}); } @Override public void attach(Observer ob) { this.observers.add(ob); } }
- 测试Code
@Test public void test_observer(){ Subject subject = new AsyncSubject(); subject.attach(new DefaultObserver()); subject.attach(new DefaultObserver()); subject.attach(new DefaultObserver()); subject.attach(new DefaultObserver()); subject.attach(new DefaultObserver()); subject.nodifyObservers("observer pattern test"); }
- 测试结果
observer pattern test: pool-1-thread-1 observer pattern test: pool-1-thread-2 observer pattern test: pool-1-thread-3 observer pattern test: pool-1-thread-4 observer pattern test: pool-1-thread-5
通过引入线程池的方式来解决同步中可能存在的问题,Spring中的多播器也是一样的原理,有兴趣的同学,可以研究研究。