设计原理4:为了交互对象之间的松耦合设计而努力
观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
案例:类似于邮件主题和邮件订阅者的关系。订阅的主题有了新内容会及时的给订阅者“推”最新的邮件,有一点不同,观察者模式也可以是被“拉”的。
注:这两种形式的观察者模式在JDK中广泛使用,是最多的模式之一
实现:
可以使用JDK自带的java.util.Observer 以及 java.util.Observable实现:
public class PatternDemo {
public static void main(String[] args) {
EmailSubject emailSubject = new EmailSubject();
King king = new King(emailSubject);
Knight knight = new Knight(emailSubject);
emailSubject.setContent("one content");
king.unregisterSubject(emailSubject);
emailSubject.setContent("two content");
knight.unregisterSubject(emailSubject);
emailSubject.setContent("three content");
}
}
public class EmailSubject extends Observable {
public static final String SUBJECT_NAME = "Email Subject";
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
setChanged();
notifyObservers(content);
}
}
public class King implements Observer {
public King(Observable o) {
o.addObserver(this);
}
public void registerSubject(Observable o) {
o.addObserver(this);
}
public void unregisterSubject(Observable o) {
o.deleteObserver(this);
}
@Override
public void update(Observable o, Object args) {
EmailSubject eSubject = (EmailSubject) o;
System.out.println(eSubject.SUBJECT_NAME + " send king " + args);
}
}
public class Knight implements Observer {
public Knight(Observable o) {
o.addObserver(this);
}
public void registerSubject(Observable o) {
o.addObserver(this);
}
public void unregisterSubject(Observable o) {
o.deleteObserver(this);
}
@Override
public void update(Observable o, Object args) {
EmailSubject eSubject = (EmailSubject) o;
System.out.println(eSubject.SUBJECT_NAME + " send knight " + args);
}
}
运行结果:
Email Subject send knight one content
Email Subject send king one content
Email Subject send knight two content
显然,这个结果貌似和我要的有点不一样,我是先注册的king,然后是knight,结果他先给knight发了,虽然这是JDK内部实现的问题,但是对于我们实际要求还是不一样,而且根据之前提到的设计原理“针对接口编程”,以及《Head First》中提及到的Observable的黑暗面:
1这是一个类,不是一个接口,甚至没有实现一个接口,限制了使用和复用;
2关键方法setChanged()被保护,意味除非继承它,否则你无法创建其实例并组合到你自己的对象中来,这个设计违反了“多用组合,少用继承”。
因此在熟悉了观察者模式后,大可以自己写一个:
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
public interface Observer {
public void update(Subject subject, Object o);
}
public class EmailSubject implements Subject {
public static final String SUBJECT_NAME = "Email Subject";
private String content;
private List<Observer> observers;
private boolean changed;
public void setChanged() {
changed = true;
}
public EmailSubject() {
observers = new LinkedList<Observer>();
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
setChanged();
notifyObservers();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
int index = observers.indexOf(o);
if (index >= 0) {
observers.remove(index);
}
}
@Override
public void notifyObservers() {
if (changed) {
for (Observer o: observers) {
o.update(this, getContent());
}
}
changed = false;
}
}
public class Knight implements Observer {
public Knight(Subject s) {
s.registerObserver(this);
}
public void registerSubject(Subject s) {
s.registerObserver(this);
}
public void unregisterSubject(Subject s) {
s.removeObserver(this);
}
@Override
public void update(Subject subject, Object o) {
EmailSubject eSubject = (EmailSubject) subject;
System.out.println(eSubject.SUBJECT_NAME + " send knight " + o);
}
}
public class King implements Observer {
public King(Subject s) {
s.registerObserver(this);
}
public void registerSubject(Subject s) {
s.registerObserver(this);
}
public void unregisterSubject(Subject s) {
s.removeObserver(this);
}
@Override
public void update(Subject subject, Object o) {
EmailSubject eSubject = (EmailSubject) subject;
System.out.println(eSubject.SUBJECT_NAME + " send king " + o);
}
}