观察者模式也叫做发布订阅模式(Publish/subscribe),它是一个经常在项目中使用的模式.
定义
定义对象之间一对多的以来关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
【观察者模式最大的优点就是使得增加观察者和删除观察者变得很容易,然后通知观察者的方式是中断,不是轮询,提高CPU利用率】
例子:李斯让间谍监控韩非子,然后报告给秦始皇
【因为观察者模式非常简单,所以就不多说了,下面 的两个代码一对比就懂了】
我们先来看没有使用观察者模式的时候的样子,直接见代码
//韩非子接口
public interface IHanFeiZi {
//吃早饭
public void haveBreakfast();
//娱乐活动
public void havefun();
}
/**
* 韩非子
*/
public class HanFeiZi implements IHanFeiZi {
private boolean isHavingBreakfast = false;
private boolean isHavingFun = false;
@Override
public void haveBreakfast() {
System.out.println("韩非子:开始吃饭了...");
this.isHavingBreakfast = true;
}
@Override
public void havefun() {
System.out.println("韩非子:开始娱乐了...");
this.isHavingFun = true;
}
public boolean isHavingBreakfast(){
return isHavingBreakfast;
}
public void setHavingBreakfast(boolean isHavingBreakfast){
this.isHavingBreakfast = isHavingBreakfast;
}
public boolean isHavingFun(){
return isHavingFun;
}
public void setHavingFun(boolean isHavingFun){
this.isHavingFun = isHavingFun;
}
}
//李斯接口
public interface IliSi {
public void update(String context);
}
public class LiSi implements IliSi{
@Override
public void update(String context) {
System.out.println("李斯:观察到韩非子活动,开始向老板汇报了...");
this.reportToQiShiHuang(context);
System.out.println("李斯:汇报完毕!");
}
private void reportToQiShiHuang(String reportContext){
System.out.println("李斯:报告,秦老板!韩非子有活动了---->" + reportContext);
}
}
//间谍,实现Thread接口
public class Watch extends Thread {
private HanFeiZi hanFeiZi;
private LiSi liSi;
private String type;
public Watch(HanFeiZi _hanFeiZi, LiSi _liSi, String _type){
this.hanFeiZi = _hanFeiZi;
this.liSi = _liSi;
this.type = _type;
}
@Override
public void run(){
while(true){
if(this.type.equals("breakfast")){
if(this.hanFeiZi.isHavingBreakfast()){
this.liSi.update("韩非子在吃饭");
this.hanFeiZi.setHavingBreakfast(false);
}
} else {
if(this.hanFeiZi.isHavingFun()){
this.liSi.update("韩非子在娱乐");
this.hanFeiZi.setHavingFun(false);
}
}
}
}
}
//场景类
public class Client {
public static void main(String[] args) throws InterruptedException {
LiSi liSi = new LiSi();
HanFeiZi hanFeiZi = new HanFeiZi();
Watch watchBreakfast = new Watch(hanFeiZi, liSi, "breakfast");
watchBreakfast.start();
Watch watchFun = new Watch(hanFeiZi, liSi, "fun");
watchFun.start();
hanFeiZi.haveBreakfast();
hanFeiZi.havefun();
}
}
/**
韩非子:开始吃饭了...
韩非子:开始娱乐了...
李斯:观察到韩非子活动,开始向老板汇报了...
李斯:报告,秦老板!韩非子有活动了---->韩非子在吃饭
李斯:汇报完毕!
李斯:观察到韩非子活动,开始向老板汇报了...
李斯:报告,秦老板!韩非子有活动了---->韩非子在娱乐
李斯:汇报完毕!
*/
ok,简单实现了这个功能之后问题就来了,首先,Watch是一个死循环,非常消耗系统资源。其次,如果除了李斯要监控韩非子之外又有新的人要监控他需要重新修改。
下面使用观察者模式来实现这个例子:
UML图:
public interface IHanFeiZi {
//吃早饭
public void haveBreakfast();
//娱乐活动
public void havefun();
}
//被观察者接口
public interface Observable {
//增加一个观察者
public void addObserver(Observer observer);
//删除一个观察者
public void deleteObserver(Observer observer);
//通知观察者
public void notifyObservers(String context);
}
public class HanFeiZi implements IHanFeiZi , Observable{
//定义个变长数组,存放所有的观察者
private ArrayList<Observer> observerList = new ArrayList<>();
@Override
public void haveBreakfast() {
System.out.println("韩非子:开始吃饭了...");
this.notifyObservers("韩非子在吃饭");
}
@Override
public void havefun() {
System.out.println("韩非子:开始娱乐了...");
this.notifyObservers("韩非子在娱乐");
}
@Override
public void addObserver(Observer observer) {
this.observerList.add(observer);
}
@Override
public void deleteObserver(Observer observer) {
this.observerList.remove(observer);
}
@Override
public void notifyObservers(String context) {
for(Observer o : observerList){
o.update(context);
}
}
}
//观察者接口
public interface Observer {
//一旦发现别人有动静,自己也要行动
public void update(String context);
}
//下面是三个观察者
//具体的观察者
public class LiSi implements Observer {
@Override
public void update(String context) {
System.out.println("李斯:观察到韩非子活动,准备跟老板汇报!");
this.reportToQinshihuang(context);
}
private void reportToQinshihuang(String context){
System.out.println("李斯:报告,秦老板,韩非子有活动了-->" + context);
}
}
--------------------------------------------------------
public class LiuSi implements Observer {
@Override
public void update(String context) {
System.out.println("刘斯:观察到韩非子活动,我也得做出行动!");
this.cry(context);
System.out.println("刘斯: 乐死了...");
}
private void cry(String context){
System.out.println("刘斯: 因为 " + context + ", --所以我快乐");
}
}
---------------------------------------------------------
public class WangSi implements Observer {
@Override
public void update(String context) {
System.out.println("王斯:观察到韩非子活动,我也得做出行动!");
this.cry(context);
System.out.println("王斯: 哭死了...");
}
private void cry(String context){
System.out.println("王斯: 因为 " + context + ", --所以我悲伤");
}
}
public class Client {
public static void main(String[] args) {
Observer liSi = new LiSi();
Observer wangSi = new WangSi();
Observer liuSi = new LiuSi();
HanFeiZi hanFeiZi = new HanFeiZi();
hanFeiZi.addObserver(liSi);
hanFeiZi.addObserver(wangSi);
hanFeiZi.addObserver(liuSi);
hanFeiZi.haveBreakfast();
}
}
/**
韩非子:开始吃饭了...
李斯:观察到韩非子活动,准备跟老板汇报!
李斯:报告,秦老板,韩非子有活动了-->韩非子在吃饭
王斯:观察到韩非子活动,我也得做出行动!
王斯: 因为 韩非子在吃饭, --所以我悲伤
王斯: 哭死了...
刘斯:观察到韩非子活动,我也得做出行动!
刘斯: 因为 韩非子在吃饭, --所以我快乐
刘斯: 乐死了...
*/