概述
当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。又叫发布-订阅(Publish/Subscribe)模式
涉及角色
- Subject
抽象主题角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。 - ConcreteSubject
具体主题角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。 - Observer
抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。 - ConcreteObserver
具体观察者角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。
UML
使用场景
- 一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
- 对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
- 一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的
优点
- 两个对象之间松耦合,依然可以交互,但是不太清楚彼此的细节
- 观察者模式支持“广播通信”。主题会向所有的观察者发出通知
缺点
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化
代码示例
比如日常生活中:爷爷奶奶帮忙带孩子,小孩是主题,爷爷奶奶是观察者
package com.designpattern.observer;
public interface Senior {
public void update(String state);
}
package com.designpattern.observer;
public class Grandma implements Senior {
@Override
public void update(String action) {
// TODO Auto-generated method stub
System.err.println("grandma receive :"+action);
}
}
package com.designpattern.observer;
public class Grandpa implements Senior {
@Override
public void update(String action) {
// TODO Auto-generated method stub
System.err.println("grandpa receive :"+action);
}
}
package com.designpattern.observer;
import java.util.ArrayList;
import java.util.List;
public abstract class Children {
private List<Senior> seniorList = new ArrayList<Senior>();
public void add(Senior senior) {
seniorList.add(senior);
System.out.println("add senior: "+senior.getClass().getName());
}
public void remove(Senior senior) {
seniorList.remove(senior);
System.out.println("remove senior: "+senior.getClass().getName());
}
public void nodifySeniors(String action) {
for (Senior senior : seniorList) {
senior.update(action);
}
}
}
package com.designpattern.observer;
public class Xiaoming extends Children{
private String action;
public String getState() {
return action;
}
public void change(String action){
this.action = action;
System.out.println("Xiaoming change: " + action);
this.nodifySeniors(action);
}
}
package com.designpattern.observer;
public class TestMain {
public static void main(String[] args) throws InterruptedException {
Xiaoming xiaoming = new Xiaoming();
Grandpa grandpa = new Grandpa();
Grandma grandma = new Grandma();
xiaoming.add(grandpa);
xiaoming.add(grandma);
Thread.sleep(1000);
xiaoming.change("cry");
Thread.sleep(1000);
xiaoming.remove(grandma);
Thread.sleep(1000);
xiaoming.change("haha");
}
}
运行结果:
add senior: com.designpattern.observer.Grandpa
add senior: com.designpattern.observer.Grandma
Xiaoming change: cry
grandpa receive :cry
grandma receive :cry
remove senior: com.designpattern.observer.Grandma
Xiaoming change: haha
grandpa receive :haha
此模式未完待续……还在学习推模式和拉模式的区别,学习完补充