观察者模式(Observer)
wiki: The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
主要用于“事件驱动”实现分布式事物处理(Event Handling)。 同义: 发布-订阅模式(pub-sub)、模型-视图模式(Model-View)、源-收听者(Listener)模式或从属者模式
类型:行为型模式
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern) 比如,当一个对象被修改时,则会自动通知它的依赖对象,通常是通过调用他们的一个方法 观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
观察者模式解决了以下问题:
A one-to-many dependency between objects should be defined without making the objects tightly coupled.
It should be ensured that when one object changes state an open-ended number of dependent objects are updated automatically.
It should be possible that one object can notify an open-ended number of other objects.
UML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 @startuml interface Observable{ + registerObserver(Observer) + unregisterObserver(Observer) + notifyObservers() } abstract class Subject{ + observerCollection:Observer + registerObserver(Observer) + unregisterObserver(Observer) + notifyObservers() } class ConcreteSubjectA{ + observerCollection:Observer + registerObserver(Observer) + unregisterObserver(Observer) + notifyObservers() } interface Observer{ + update() } class ConcreteObserverA{ + update() } class ConcreteObserverB{ + update() } Observable <|.. Subject Observer --o Subject:observerCollection Observer <|.. ConcreteObserverA Observer <|.. ConcreteObserverB Subject <|-- ConcreteSubjectA note left of Subject <b>notifyObservers()</b> for observer in observerCollection call observer update end note @enduml
主要的四种角色:抽象主题、具体主题、抽象观察者、具体观察者
抽象主题–被观察者(Subject)
具体主题(ConcreteSubject)
抽象观察者(Observer)
具体观察者(ConcreteObserver)
观察者模式实例 观察者接口
1 2 3 4 5 6 7 8 public interface Observer { void update (Subject observable,Object arg) ; }
具体观察者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class ConcreteObserverA implements Observer { @Override public void update (Subject observable,Object arg) { System.out.println("ConcreteObserverA accept and update..." ); System.out.println("Object : " + observable); System.out.println("args : " + arg); } } public class ConcreteObserverB implements Observer { @Override public void update (Subject observable,Object arg) { System.out.println("ConcreteObserverB accept and update..." ); System.out.println("Object : " + observable); System.out.println("args : " + arg); } }
可被观察接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public interface Observable { void registerObserver (Observer observer) ; void unregisterObserver (Observer observer) ; void notifyObservers () ; }
被观察者抽象类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public abstract class Subject implements Observable { private Vector<Observer> observers = new Vector<>(); @Override public void registerObserver (Observer observer) { observers.add(observer); } @Override public void unregisterObserver (Observer observer) { observers.remove(observer); } @Override public void notifyObservers () { for (Observer observer : observers) { observer.update(this ,null ); } } }
具体被观察者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class ConcreteSubjectA extends Subject { private String data; public String getData () { return data; } public void setData (String data) { this .data = data; notifyObservers(); } }
场景类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Client { public static void main (String[] args) { Observer observerA = new ConcreteObserverA(); Observer observerB = new ConcreteObserverB(); ConcreteSubjectA subject = new ConcreteSubjectA(); subject.registerObserver(observerA); subject.registerObserver(observerB); subject.setData("ok" ); subject.unregisterObserver(observerB); subject.setData("test" ); } }
使用JDK提供的API 通过实现java.util.Observer接口,生成观察者
1 2 3 4 5 6 7 8 public class ConcreteObserver implements Observer { @Override public void update (Observable o, Object arg) { System.out.println("ConcreteObserver accept..." ); System.out.println("Object : " + o); System.out.println("Observers count: " + o.countObservers()); } }
通过继承java.util.Observable类,实现被观察者
1 2 3 4 5 6 7 8 9 10 11 12 public class ConcreteObserved extends Observable { private String data; public void setData (String data) { this .data = data; this .setChanged(); this .notifyObservers(); } }
场景类
1 2 3 4 5 6 7 8 9 10 11 12 public class Client { public static void main (String[] args) { ConcreteObserver observer = new ConcreteObserver(); ConcreteObserved observed = new ConcreteObserved(); observed.addObserver(observer); observed.setData("ok" ); } }
观察者模式优点和缺点 优点:
观察者和被观察者之间抽象耦合
观察者模式容易扩展,被观察者只持有观察者集合,并不需要知道具体观察者内部的实现
缺点:
如果观察者太多,被观察者通知观察者消耗的时间很多,影响系统的性能
当观察者集合中的某一观察者错误时就会导致系统卡壳,因此一般会采用异步方式
使用:
MVC:观察目标就是 Model ,观察者就是 View, Controller 为两者之间的中介
发布-订阅模式(pub-sub)
Tomcat
控制组件生命周期的Lifecycle
,还有对Servlet
实例的创建、Session
的管理、Container
等
Spring中ApplicationListener