记得16年初第一次学习了23种设计模式,但是除了少数几个简单的外,其他的很多都是学了个似懂非懂,以至于有人问起甚至说不上来,现在想想,其实就是没看懂而已。例如观察者模式,其实原理很简单,但是当时并没有能静下心来细细总结,在此自我反思,也望后来者共勉。
而关于设计模式是否能够被用的到这个问题,其实当我们遇到很多业务场景的时候,也会自然而然的想到与设计模式类似的思路,所以设计模式并没有我多年前认为的那么深不可测。然后就是类似于发布订阅这种需求,在如今大数据高并发的前提下,也已经有了很多完善的中间件框架,所以本人用到的极少。但并不是说没有用,例如JDK中大量使用的“委托”(并不在23中设计模式中),可以重用大量代码,是我最喜欢的设计模式,以后的博客中会详细描述。
废话说完 ,开始正题:
观察者模式,其实就是发布订阅模式,发布者发布信息,订阅者订阅就能收到信息,没订阅就收不到信息。
应用场景:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
实现方式:
类图:
代码(参考了runnoob网站案例,稍作精简修改):
1、首先我定义了一个公众号,持有一个被观察者对象的集合,发布文章时会调用方法通知所有观察者:
package com.pat.observer;
/**
* 被观察者-模仿公众号
* @author Administrator
*
*/
import java.util.ArrayList;
import java.util.List;
public class Subject {
//即将更新的头条文章
private String articles;
//持有观察者集合
private List<Observer> observers=new ArrayList<>();
public String getArticles() {
return articles;
}
public void setArticles(String articles) {
this.articles = articles;
notifyAllObservers();
}
public void attach(Observer observer) {
observers.add(observer);
}
public void notifyAllObservers() {
for(Observer obs:observers) {
obs.update();
}
}
}
2、定义一个订阅者(观察者)接口或者抽象类:
package com.pat.observer;
/**
* 观察者
* @author Administrator
*
*/
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
3、假设存在A、B、C三位订阅者,继承观察者对象:
package com.pat.observer;
public class ObserverA extends Observer{
@Override
public void update() {
System.out.println("观察者A查看订阅的Subject公众号>>>"+subject.getArticles());
}
public ObserverA(Subject subject) {
this.subject=subject;
this.subject.attach(this);
}
}
package com.pat.observer;
public class ObserverB extends Observer{
@Override
public void update() {
System.out.println("观察者B查看订阅的Subject公众号>>>"+subject.getArticles());
}
public ObserverB(Subject subject) {
this.subject=subject;
this.subject.attach(this);
}
}
package com.pat.observer;
public class ObserverC extends Observer{
@Override
public void update() {
System.out.println("观察者C查看订阅的Subject公众号>>>"+subject.getArticles());
}
public ObserverC(Subject subject) {
this.subject=subject;
this.subject.attach(this);
}
}
4、测试类中我们被观察者(被订阅者)发布文章:
package com.pat.observer;
public class Test {
public static void main(String[] args) {
Subject sub = new Subject();
new ObserverA(sub);
new ObserverB(sub);
new ObserverC(sub);
sub.setArticles("Subject更新文章《如何高效装逼》");
}
}
5、结果:
观察者A查看订阅的Subject公众号>>>Subject更新文章《如何高效装逼》
观察者B查看订阅的Subject公众号>>>Subject更新文章《如何高效装逼》
观察者C查看订阅的Subject公众号>>>Subject更新文章《如何高效装逼》