1. 定义
观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在观察者模式中,主题是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。(百度百科)
2. 角色
观察者模式所涉及的角色有:
2.1 抽象主题(Subject)
它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
2.2 具体主题(Concrete Subject):
将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
2.3 抽象观察者(Observer):
为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
2.4 具体观察者(Concrete Observer):
实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
3. 实例
例子:用户只有打开电视,并且将频道设置到CCTV,才能接收到新闻联播。而对于CCTV来说,它只负责播放新闻联播,只有频道对了的观众才能接收到CCTV的新闻联播,如果用户在播放期间调台了,则再也接收不到CCTV的新闻联播。
3.1 定义抽象的观察者接口
package zzw.cn.observer;
public interface Observer
{
public void update(String msg);
}
3.2 定义抽象的被观察者接口
package zzw.cn.observer;
public interface Observerable
{
public void registerObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObserver();
}
3.3 定义被观察者,实现了被观察者接口
package zzw.cn.observer;
import java.util.ArrayList;
import java.util.List;
public class CCTVServer implements Observerable
{
private String message;
private List<Observer> list;
public CCTVServer()
{
list = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer observer)
{
list.add(observer);
}
@Override
public void removeObserver(Observer observer)
{
if (null != list)
{
if (!list.isEmpty())
{
list.remove(observer);
}
}
}
public void setMessage(String msg)
{
this.message = msg;
notifyObserver();
}
@Override
public void notifyObserver()
{
for (int i = 0; i < list.size(); i++)
{
Observer observer = list.get(i);
observer.update(message);
}
}
}
3.4 定义了观察者,实现了观察者接口
package zzw.cn.observer;
public class User implements Observer
{
String name;
String message;
public User(String name)
{
this.name = name;
}
@Override
public void update(String msg)
{
this.message = msg;
read();
}
public void read()
{
System.out.println(name + " 收到推送消息: " + message);
}
}
3.5 测试类
package zzw.cn.observer;
public class TestObserver
{
public static void main(String[] args)
{
CCTVServer server=new CCTVServer();
Observer zhangsan=new User("张三");
Observer lisi=new User("李四");
Observer wangwu=new User("王五");
server.registerObserver(zhangsan);
server.registerObserver(lisi);
server.registerObserver(wangwu);
server.setMessage("今天是2019/07/28");
server.removeObserver(zhangsan);
server.removeObserver(lisi);
server.setMessage("今天是2019/07/29");
}
}
运行结果:
张三 收到推送消息: 今天是2019/07/28
李四 收到推送消息: 今天是2019/07/28
王五 收到推送消息: 今天是2019/07/28
王五 收到推送消息: 今天是2019/07/29
Process finished with exit code 0
4. 观察者模式的优缺点
观察者模式的主要的作用就是对对象解耦,将观察者和被观察者完全隔离。
观察者模式的优点:
观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。
观察者模式的缺点:
程序中包括一个被观察者和多个被观察者额,开发和调试比较复杂,而且Java中的消息的通知默认是顺序执行的,一个观察者的卡顿会影响整体的执行效率。在这种情况下,一般考虑采用异步的方式。