观察者模式,又叫做发布-订阅(Publish/Subscribe)模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
举例:
在工作的时候,如果老板不在,有的人可能会放松一下,看看新闻或者看看股票。这个时候需要有个人时刻观察老版的动向,如果老板回来了,就通知大家一声,让大家赶紧开始工作。
1.观察者接口,就是发现主题变化时,需要执行的方法。
public interface IObserver {
void goToWork();
}
2.实际的观察者们
//看新闻的同事
public class NewsObserver1 implements IObserver {
private String name;
public NewsObserver(String name) {
this.name = name;
}
@Override
public void goToWork() {
System.out.println(name + "停止看新闻,开始工作。");
}
}
//看体育赛事的同事
public class SportsObserver1 implements IObserver {
private String name;
public SportsObserver(String name) {
this.name = name;
}
@Override
public void goToWork() {
System.out.println(name + "停止看体育赛事,开始工作。");
}
}
// 看股票的同事
public class StockObserver1 implements IObserver {
private String name;
public StockObserver(String name) {
this.name = name;
}
@Override
public void goToWork() {
System.out.println(name + "停止炒股,开始工作。");
}
}
3.主题接口,主要负责添加、删除观察者,以及发送通知
public interface ISubject {
void addObserver(IObserver iObserver);
void delObserver(IObserver iObserver);
void bossReturn();
}
4.主题的实现类
import java.util.ArrayList;
import java.util.List;
public class NotifySubject1 implements ISubject {
List<IObserver> observers;
@Override
public void addObserver(IObserver iObserver) {
if (observers == null) {
observers = new ArrayList<>();
}
observers.add(iObserver);
}
@Override
public void delObserver(IObserver iObserver) {
if (observers == null || observers.isEmpty()) {
return;
}
observers.remove(iObserver);
}
// 通知每一个加入过的观察者,去执行主题变更时的方法
public void notifyObserver() {
for (IObserver iObserver : observers) {
iObserver.goToWork();
}
}
@Override
public void bossReturn() {
System.out.println("boss回公司了,大家赶紧开始工作");
notifyObserver();
}
}
5.主程序代码
//主程序代码
public class Test1 {
public static void main(String[] args) {
IObserver xiaoMing = new NewsObserver1("小明");
IObserver xiaoWang = new SportsObserver1("小王");
IObserver xiaoLi = new StockObserver1("小李");
ISubject boss = new NotifySubject1();
boss.addObserver(xiaoMing);
boss.addObserver(xiaoWang);
boss.addObserver(xiaoLi);
boss.bossReturn();
System.out.println("=== 这次忘记通知小王了 ===");
boss.delObserver(xiaoWang);
boss.bossReturn();
System.out.println("=== 小王被老板逮到了 ===");
}
}
运行结果如下:
Java的java.util包中提供的Observable类和Observer接口也可以实现观察者模式。
其中实现Observable接口的被观察类,在调用setChanged()方法时,表示被观察者发生变化,此时被观察者调用notifyObservers()方法时,会调用实现Observer接口的观察者类中的update(Observable o, Object arg)方法。如果被观察者调用notifyObservers(Object arg)方法,还可以传递需要的参数,通过addObserver(Observer o)、deleteObserver(Observer o)方法可以添加、删除观察者。
下面看调整过后的代码:
1.被观察的主题类
import java.util.Observable;
public class NotifySubject2 extends Observable {
String message;
public NotifySubject2() {
message = "你们玩吧,我帮你们观察boss";
System.out.println("NotifySubject: " + message);
}
public void bossReturn(){
message = "boss回公司了,大家赶紧开始工作";
System.out.println("NotifySubject: " + message);
setChanged();
this.notifyObservers(message);
}
}
2.观察者类
import java.util.Observable;
import java.util.Observer;
//看新闻的同事
public class NewsObserver2 implements Observer {
private String name;
public NewsObserver2(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(name + "收到消息:" + arg + "。 停止看新闻,开始工作。");
}
}
import java.util.Observable;
import java.util.Observer;
//看体育赛事的同事
public class SportsObserver2 implements Observer {
private String name;
public SportsObserver2(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(name + "收到消息:" + arg + "。 停止看体育赛事,开始工作。");
}
}
import java.util.Observable;
import java.util.Observer;
//看股票的同事
public class StockObserver2 implements Observer {
private String name;
public StockObserver2(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(name + "收到消息:" + arg + "。 停止炒股,开始工作。");
}
}
3.主程序:
import java.util.Observer;
//主程序代码
public class Test2 {
public static void main(String[] args) {
Observer xiaoMing = new NewsObserver2("小明");
Observer xiaoWang = new SportsObserver2("小王");
Observer xiaoLi = new StockObserver2("小李");
NotifySubject2 boss = new NotifySubject2();
boss.addObserver(xiaoLi);
boss.addObserver(xiaoWang);
boss.addObserver(xiaoMing);
boss.bossReturn();
System.out.println("=== 这次忘记通知小王了 ===");
boss.deleteObserver(xiaoWang);;
boss.bossReturn();
System.out.println("=== 小王被老板逮到了 ===");
}
}
运行结果如下:
具体的Observer和Observable详解可点击本处