观察者模式(发布订阅模式)
蒙蒙是公司秘书,华华和昆昆是公司职员(股票观察人),他们经常在上班期间看股票,如果被老板看到,后果很严重的.所以蒙蒙会在老板回来之前通知他们.
public class Secretary {
//同事列表
private List<StockObserver> stockObservers=new ArrayList<StockObserver>();
//通知的内容
private String message;
//有几个同事给前台帮忙,就给集合增加几个对象
public void add(StockObserver stockObserver) {
stockObservers.add(stockObserver);
}
//等老板来时,给登记的同事发通知,老板来了
public void inform() {
for (StockObserver stockObserver : stockObservers) {
//得到前台的通知,赶紧采取行动
stockObserver.action();
}
}
//通知内容的get和set方法
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
//观看股票的同事
public class StockObserver {
private String name;
private Secretary secretary;
public StockObserver(String name, Secretary secretary) {
this.name = name;
this.secretary = secretary;
}
public void action() {
System.out.println(name+": "+secretary.getMessage());
}
}
public class Demo1 {
public static void main(String[] args) {
//前台秘书蒙蒙
Secretary mengmeng=new Secretary();
//看股票的同事
StockObserver workmate1=new StockObserver("华华", mengmeng);
StockObserver workmate2=new StockObserver("昆昆", mengmeng);
//前台记下了拜托她的同事
mengmeng.add(workmate1);
mengmeng.add(workmate2);
//发现老板回来,写通知消息
mengmeng.setMessage("老板回来了,关闭股票行情,继续工作");
//短信通知登记的同事
mengmeng.inform();
}
}
输出结果:
华华: 老板回来了,关闭股票行情,继续工作
昆昆: 老板回来了,关闭股票行情,继续工作
问题描述:秘书类和观察者类耦合性太大,可以定义分别为秘书(如果还有其他类可以为观察者通知消息)和观察者(有的观察者可能在看NBA)分别定义一个抽象类,让具体类秘书和股票观察者继承各自的抽象类.
public interface Informer {
public abstract void add(Observer observer);
public abstract void delete(Observer observer);
public abstract void inform();
}
public class Secretary implements Informer{
//同事列表
private List<Observer> observers=new ArrayList<Observer>();
//通知的内容
private String message;
//有几个同事让前台帮忙,就给集合增加几个对象
public void add(Observer observer) {
observers.add(observer);
}
public void delete(Observer observer) {
observers.remove(observer);
}
//等老板来时,给登记的同事发通知,老板来了
public void inform() {
for (Observer observer : observers) {
//得到前台的通知,赶紧采取行动
observer.action(message);
}
}
//通知内容的get和set方法
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
/**
*下面的类用抽象类好呢,还是用接口好呢?
*使用抽象类,可以共用一些代码,但是在现实编程中,具体的观察者可能是风马牛不相及的类,这时可以使用接口
*/
public abstract class Observer {
protected String name;
protected Informer informer;
public Observer(String name, Informer informer) {
this.name = name;
this.informer = informer;
}
//更新方法
public abstract void action(String message);
}
//观看股票的同事
public class StockObserver extends Observer{
public StockObserver(String name, Informer informer) {
super(name, informer);
}
public void action(String message) {
System.out.println(name+": "+message+"关闭股票行情,继续工作");
}
}
//观看NBA的同事
public class NBAObserver extends Observer{
public NBAObserver(String name, Informer informer) {
super(name, informer);
}
public void action(String message) {
System.out.println(name+": "+message+"关闭NBA直播,继续工作");
}
}
public class Demo1 {
public static void main(String[] args) {
//前台秘书蒙蒙
Informer mengmeng=new Secretary();
//看股票的同事
StockObserver workmate1=new StockObserver("华华", mengmeng);
StockObserver workmate2=new StockObserver("昆昆", mengmeng);
//前台记下了拜托她的同事
mengmeng.add(workmate1);
mengmeng.add(workmate2);
//发现老板回来,写通知消息
Secretary meng=(Secretary)mengmeng;
meng.setMessage("老板回来了");
//短信通知登记的同事
meng.inform(); //或者mengmeng.inform();也是可以的
}
}
输出结果:
华华: 老板回来了关闭股票行情,继续工作
昆昆: 老板回来了关闭股票行情,继续工作
观察者模式:
定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有的观察者对象,使它们能够自动更新自己
观察者模式的好处:
将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象的一致性.我们不希望为了维护一致性使各类紧密耦合,这样会给维护,扩展和复用带来不便.Informer类可以有任意数目依赖它的Observer类,一旦Informer的状态发生改变,所有的Observer都可以得到通知,发出通知时,Informer不需要知道具体的Observer,它根本不需要知道.而任何一个具体的Observer互相之间也不耦合.
说白了,观察者模式所做的工作其实就是在解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体.从而实现各自的变化都不会影响另一边的变化.体现了依赖倒转原则.
何时使用观察者模式:
当一个对象的改变需要同时改变其他对象时,或者它不知道有多少对象有待改变,也应该考虑使用观察者模式