设计模式学习(二)-- 观察者模式 Observer Pattern
2015-03-19 09:41
405 查看
观察者模式:定义了对象之间的一对多依赖,这样当一个对象状态改变的时候,它的所有依赖者都会收到通知并自动更新。
设计原则:为了交互对象之间的松耦合设计而努力。
松耦合的设计让对象之间的依赖降到最低,这样便于建立更加有弹性的系统,应对变化。
实现观察者模式的方法不止一种,但是包含Subject和Observer接口的设计实现最常见。
主题只需要知道观察者实现了观察者接口Observer,不需要知道观察者的具体类是谁,做了什么。主题唯一依赖的是一个实现了观察者Observer接口的对象列表,可以随时增加,删除观察者,并方便地通知所有列表中的观察者。
观察者只需要持有一个主题的对象,用于注册成为主题的观察者,这样就可以接受到主题状态改变的通知。
观察者模式类图:
主题是拥有数据或者状态的对象,观察者依赖主题来获取数据或者状态的改变。一个主题可以有多个观察者依赖它。主题负责在数据或者状态改变的时候,将改变通知所有依赖它的观察者。观察者必须注册具体主题,以便接受更新。
代码实现:
这是主题接口,对象使用此接口注册为观察者,或者把自己从观察者中删除。实现此接口的具体主题还必须实现NotifyObservers()方法用于在状态改变时通知所有的观察者。
具体主题类实现主题接口Subject,提供注册和删除观察者的方法,以及状态改变时通知所有观察者的方法。此处具体主题类维护一个ArrayList observers用来记录所有注册的观察者,以便实现注册、删除和通知观察者的方法。此外,具体主题类是拥有数据的对象,提供设置和获取这些数据的方法。ChangeDate(String name, int age)方法改变数据状态并且调用NotifyObservers()通知该主题维护的所有观察者。NotifyObservers()会调用每个观察者的Update()方法来实现数据状态改变的通知。
所有潜在观察者必须实现观察者接口,这个接口只有一个Update()方法,当主题状态改变时它被调用。
具体观察者实现观察者接口Observer,实现Update方法用于在主题的数据状态改变时更新这些数据状态。具体观察者必须注册主题,才能接收主题的更新通知。此处观察者持有一个具体主题的对象MySubject mySubject,在构造函数里面注册成为MySubject主题的观察者。
注意:代码的实现不能依赖于观察者被通知的次序。因为一旦主题/观察者的实现改变了,通知的次序就会改变,依赖于某一特定实现的通知次序,是错误的。
Java API 内置观察者模式:java.util.Observable类和java.util.Observer为开发者接口提供了观察者模式。Observable类就是主题,具体的主题类需要继承Observable类。
由于Observable是一个类,所以具体主题就不能同时拥有Observable类和另一个超类的行为。
设计原则:为了交互对象之间的松耦合设计而努力。
松耦合的设计让对象之间的依赖降到最低,这样便于建立更加有弹性的系统,应对变化。
实现观察者模式的方法不止一种,但是包含Subject和Observer接口的设计实现最常见。
主题只需要知道观察者实现了观察者接口Observer,不需要知道观察者的具体类是谁,做了什么。主题唯一依赖的是一个实现了观察者Observer接口的对象列表,可以随时增加,删除观察者,并方便地通知所有列表中的观察者。
观察者只需要持有一个主题的对象,用于注册成为主题的观察者,这样就可以接受到主题状态改变的通知。
观察者模式类图:
主题是拥有数据或者状态的对象,观察者依赖主题来获取数据或者状态的改变。一个主题可以有多个观察者依赖它。主题负责在数据或者状态改变的时候,将改变通知所有依赖它的观察者。观察者必须注册具体主题,以便接受更新。
代码实现:
/** * * @author Yves */ public interface Subject{ public void Register(Observer o); public void Remove(Observer o); public void NotifyObservers(); }
这是主题接口,对象使用此接口注册为观察者,或者把自己从观察者中删除。实现此接口的具体主题还必须实现NotifyObservers()方法用于在状态改变时通知所有的观察者。
class MySubject implements Subject { private String name; private int age; //observers list private ArrayList observers; public MySubject() { //create observers list in the Contruct method. observers = new ArrayList(); } @Override public void Register(Observer o) { observers.add(o); } @Override public void Remove(Observer o) { if (observers != null && !observers.isEmpty() && observers.contains(o)) { observers.remove(o); } } @Override public void NotifyObservers() { for (Object observer : observers) { Observer ob = (Observer) observer; ob.Update(name, age); } } public void ChangeDate(String name, int age) { this.SetName(name); this.SetAge(age); //notify all observers this.NotifyObservers(); } public void SetName(String name) { this.name = name; } public void SetAge(int age) { this.age = age; } }
具体主题类实现主题接口Subject,提供注册和删除观察者的方法,以及状态改变时通知所有观察者的方法。此处具体主题类维护一个ArrayList observers用来记录所有注册的观察者,以便实现注册、删除和通知观察者的方法。此外,具体主题类是拥有数据的对象,提供设置和获取这些数据的方法。ChangeDate(String name, int age)方法改变数据状态并且调用NotifyObservers()通知该主题维护的所有观察者。NotifyObservers()会调用每个观察者的Update()方法来实现数据状态改变的通知。
/** * * @author Yves */ public interface Observer{ public void Update(String name, int age); }
所有潜在观察者必须实现观察者接口,这个接口只有一个Update()方法,当主题状态改变时它被调用。
class ObserverA implements Observer { private String name; private int age; private MySubject mySubject; public ObserverA(MySubject mySubject) { this.mySubject = mySubject; //Register this observer to the observer list of Subject object. this.mySubject.Register(this); } @Override public void Update(String name, int age) { this.name = name; this.age = age; this.Display(); } public void Display() { System.out.println("User name is: " + name + ", User age is: " + age); } }
具体观察者实现观察者接口Observer,实现Update方法用于在主题的数据状态改变时更新这些数据状态。具体观察者必须注册主题,才能接收主题的更新通知。此处观察者持有一个具体主题的对象MySubject mySubject,在构造函数里面注册成为MySubject主题的观察者。
public class ObserverPattern { public static void main(String args[]){ MySubject mys = new MySubject(); ObserverA oba = new ObserverA(mys); //register an observer, THIS ACTIION is better done in the Observer class. //mys.Register(oba); //data change in MySubject, will notify all observers mys.ChangeDate("Yves", 18); //observers show the data oba.Display(); } }
注意:代码的实现不能依赖于观察者被通知的次序。因为一旦主题/观察者的实现改变了,通知的次序就会改变,依赖于某一特定实现的通知次序,是错误的。
Java API 内置观察者模式:java.util.Observable类和java.util.Observer为开发者接口提供了观察者模式。Observable类就是主题,具体的主题类需要继承Observable类。
由于Observable是一个类,所以具体主题就不能同时拥有Observable类和另一个超类的行为。
相关文章推荐
- 设计模式学习笔记--观察者模式(Observer Pattern)
- 设计模式学习笔记---观察者模式Observer pattern(Java版)
- 设计模式学习笔记--Observer Pattern观察者模式
- 设计模式学习——观察者模式(Observer Pattern)
- 设计模式学习——观察者模式(Observer Pattern)
- 设计模式学习总结-观察者模式(Observer Pattern)
- 设计模式学习笔记---观察者模式Observer pattern(Java版)
- 设计模式学习--观察者模式(Observer Pattern)
- Java设计模式—观察者模式(Observer pattern)
- .NET设计模式(19):观察者模式(Observer Pattern)
- 设计模式学习之路——Observer 观察者模式
- 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)
- 设计模式17:Observer Pattern (观察者模式)
- C#设计模式-观察者模式(Observer Pattern)[FreeDownload]
- 设计模式-观察者模式(Observer Pattern)
- 【转载】.NET设计模式之观察者模式(Observer Pattern)
- Net设计模式之观察者模式(Observer Pattern)(1)
- 深入浅出设计模式-002:观察者模式(Observer Pattern)
- 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)
- Net设计模式之观察者模式(Observer Pattern)(2)