导引
- 买衣服
ABCDE这堆网购达人天天盯着这件纯手工纯棉T恤,就等它降价,并点了按钮降价通知,一旦降价,得到通知,立马入手!✌
- 订报
小强是个卖报的小行家,他手上有一份订报人的地址列表,一旦有人打电话订报,他就会把地址添加到列表中然后给他送报~
- 微博
我喜欢许嵩,然后我就点关注他,一点许嵩有了新的动态,手机会通知我,然后我就去查看他的动态~~~
上述例子有一个共同的特点,一方对另一方有关注,一旦被关注的那一方发生了变化,关注的那一方也会有相应的举动。嗯,其中还有一个通知的过程哟~
其实这就是用到了观察者模式,具体谁谁,自己思考~
问题1:观察者模式是个什么东东?
回答
观察者模式是对象的行为模式,定义了一对多的依赖关系,让多个观察者同时监听同一个主题对象,当主题对象发生变化时,会通知所有观察者对象自动更新。
观察者模式还有些别称,例如发布订阅模式,模型视图模式,源-监听器模式,从属模式。
问题2:观察者模式有哪些角色?(角色定义亲请参见上图哈~)
回答
1.抽象主题角色
public interface Subject {
public void attach(Observer observer);
public void detach(Observer observer);
void notifyObservers();
}
2.具体主题角色:具体的被观察者
public class ConcreteSubject implements Subject {
//Vector:实现自动增长的对象数组
private Vector observersVector = new Vector();
@Override
public void attach(Observer observer) {
observersVector.addElement(observer);
}
@Override
public void detach(Observer observer) {
observersVector.remove(observer);
}
@Override
public void notifyObservers() {
Enumeration enumeration = observers();
while (enumeration.hasMoreElements()) {
((Observer)enumeration.nextElement()).update();
}
System.out.println("notify");
}
public Enumeration observers() {
return observersVector.elements();
}
}
3.抽象观察者角色
public interface Observer {
void update();
}
4.具体观察者角色
public class ConcreteObserver implements Observer {
@Override
public void update() {
System.out.println("I am notified");
}
}
问题3:它还有另一种写法,还有另一种写法,有另一种写法,另一种写法……吗?
回答:有的~
because:聚集管理方法是所有主题所共有的,可以把它们抽取出来,将这些方法连同聚集本身都一到抽象主题角色中去,由于notifyObserver()方法依赖于聚集对象,也可以一到抽象主题角色中去。
0.UML类图
1.抽象主题角色
abstract class Subject {
private Vector observersVector = new Vector();
public void attach(Observer observer) {
observersVector.addElement(observer);
System.out.println("attach an observe");
}
public void detach(Observer observer) {
observersVector.removeElement(observer);
}
public void notifyObservers() {
Enumeration enumeration = observers();
while (enumeration.hasMoreElements()) {
((Observer)enumeration.nextElement()).update();
}
}
public Enumeration observers() {
return observersVector.elements();
}
}
2.具体主题角色(单例)
public class ConcreteSubject extends Subject {
private String state;
private static ConcreteSubject instance = new ConcreteSubject();
private ConcreteSubject(){}
public static ConcreteSubject getInstance() {
return instance;
}
public void change(String newState) {
state = newState;
this.notifyObservers();
System.out.println("state:" + state);
}
}
3.抽象观察者对象和具体观察者对象和第一种实现相同(所以就不在啰嗦了就酱!)
4.客户端
public class Client {
private static ConcreteSubject subject = ConcreteSubject.getInstance();
private static Observer observer;
public static void main(String[] args) {
observer = new ConcreteObserver();
subject.attach(observer);
subject.change("new State");
//ConcreteSubject.getInstance().attach(observer);
}
}
5.两种方法的区别
可以看出,第二种实现与第一种实现的主要区别就是代表存储观察者对象的集合连线是从抽象主题到抽象观察者。
问题4:观察者模式有什么优点和缺点
回答
- 优点
- 松耦合,它们彼此交互,但是不清楚彼此的细节。正因为没有紧密的耦合到一起,因此它们可以属于不同的抽象化层次
- 支持广播通信,会向所观察者发送通知
- 被观察者角色所知道的只是一个具体观察者聚集,每一个具体观察者都符合一个抽象观察者的接口。o(╯□╰)o
- 主题所知道的只是一个具体的观察者列表,并不认识任何一个具体观察者,只知道它们都有一个共同的接口。(⊙_⊙)?
- 符合开闭原则
- 缺点
- 如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在被观察者之间有循环依赖的话,被观察者会出发它们之间进行循环调用,导致系统崩溃。
- 如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证是以自洽的方式进行的。(自洽是神马意思,自行百度,谢谢O(∩_∩)O)
- 虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是没有响应的机制使观察者知道所观察的对象是如何发生变化的。
- 好多缺点o(≧口≦)o
问题5:观察者模式在Android中有哪些应用捏?
广播机制,ContentObserver的注册方式,一个是同步的观察模式,一个是异步的观察者模式。
Android原生的android.database.Observable。
组件间的通信库EventBus 和 RxJava。
总结
观察者模式是对象的行为模式,定义了对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖者都会收到通知。
观察者模式有四个角色:抽象主题角色,具体主题角色,抽象观察者角色,具体观察者角色。
松耦合,不必知道对方的细节就可以调用。
有多个观察者时,不依赖于观察者被通知的顺序。
PS:参考用书:《Java与模式》