设计模式 #6 (观察者模式)
文章中所有工程代码和UML
建模文件都在我的这个GitHub
的公开库--->DesignPattern。Star
来一个好吗?秋梨膏!
观察者模式
简述:被观察者发生变化时,所有被观察者都会通知。
需求:要求报纸发布的时候,读者可以及时收到报纸的最新报道。
根据之前多次的反例经验,要做好面向接口和抽象编程的设计。
这次直接上,
正例 #1:
为观察者定义一个接口。
//观察者接口
interface Observer {
void update(String Data);
void disObservered(TheSubject subject);
void doObservered(TheSubject subject);
}
这里有一个问题:为什么不用抽象类进行抽象?
因为不知道观察者模式的应用都是怎么样的。现实编程中,具体的观察者完全有可能是风马牛不相及的类,但它们都需要根据通知者的通知来做出update()
的操作,所以让它们都实现Observer
接口,并重写相关方法即可。
定义一个观察者:
public class Reader implements Observer{
private String name ;
public Reader(String name) {
this.name = name;
}
@Override
public void update(String Data) {
System.out.println(this.name+"收到报纸,阅读最新报道:"+Data);
}
@Override
public void disObservered(TheSubject subject) {
subject.removeObserver(this);
}
@Override
public void doObservered(TheSubject subject) {
subject.addObserver(this);
}
}
//被观察者抽象类
public abstract class TheSubject {
//观察者列表
protected List<Observer> observerList = new ArrayList<>();
//加入到观察者列表
public boolean addObserver(Observer observer){
return observerList.add(observer);
}
//从观察者列表移除
public boolean removeObserver(Observer observer){
return observerList.remove(observer);
}
//变化,并通知观察者
public abstract void setChange(String Data);
//为观察者更新内容
public abstract void upDataObserver(String Data);
}
唉?那这里为什么不可以用接口呢?
注意到有一个变量observerList
了吗?
我们先假设TheSubject
抽象类是一个接口,如果是需要一个类成为被观察者,那么就会让他实现这一接口,也是需要定义它的观察者列表observerList
,如果是每一个被观察者都需要重新定义自己的观察者列表observerList
,还要在实现addObserver
、removeObserver
两个方法,这两个方法都是固定的算法。重复太多的代码就会有坏的味道的。
这时候,将重复的代码写在抽象类TheSubject
,被观察者进行继承即可。
public class News_pappers extends TheSubject{
private String news;
public String getNews() {
return news;
}
@Override
public void setChange(String Data) {
this.news ="最新报道:"+ Data;
System.out.println("发布最新报道:"+Data);
upDataObserver(Date);
}
@Override
public void upDataObserver(String Data) {
for (Observer observer : observerList) {
observer.update(Data);
}
}
}
public class postive {
/*================客户端============================*/
public static void main(String[] args) {
News_pappers newspaper = new News_pappers();
Reader lili = new Reader("lili");
Reader mumu = new Reader("mumu");
Reader shanshan = new Reader("shanshan");
newspaper.addObserver(lili);
newspaper.addObserver(mumu);
newspaper.addObserver(shanshan);
newspaper.setChange("Big News");
shanshan.disObservered(newspaper);
newspaper.setChange("small00000 News");
News_pappers news_pappers_02 = new News_pappers();
mumu.doObservered(news_pappers_02);
news_pappers_02.setChange("大新闻");
}
}
运行结果:
UML
类图:
细心的读者可能已经发现,这里遵守的设计原则有:
- 增加其他类型观察者时,只需要
Observer
接口即可;增加被观察者继承抽象类TheSubject
即可,符合开闭原则。 - 接口
Observer
和抽象类TheSubject
相互依赖,并不涉及相关具体的观察者和被观察者,符合依赖倒置原则。
其实接触过安卓都知道,安卓的内容提供者和内容观察者,广播机制都有点观察者模式的味道。
最后总结观察者模式:
- 当一个对象的改变需要同时改变其他对象的时候,而且它不知道具体有多少对象有待改变时,应该考虑使用观察者模式。
- 当一个抽象模型有两个方面,其中一方面依赖于另一方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。
- 观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
- 观察者和被观察者可以是多对多的关系。
- 观察者抽象成接口,被观察者抽象于抽象类比较合适。
这是最后一篇关于设计模式的相关随笔,回顾以往设计模式相关原创随笔请点击---> 设计原则和常用设计模式。