菜鸟教程:http://www.runoob.com/design-pattern/observer-pattern.html
Head First设计模式
一、概念:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
二、优点:
观察者和被观察者是抽象耦合的,这是最大的好处
三、缺点:
如果观察者有很多,被观察轮询通知需要很长时间,影响效率。
四、使用场景:
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
五、注意:
一般这种轮询通知,如果某一个观察者,同时又很多被观察者...,严重影响效率,甚至卡死,所以,轮询通知一般采用异步方式。
六、案例
以微信公众号推送文章为例:一个微信公众号有多个读者,当公众号有文章推送时,每个读者就会收到文章并查看,如果其中一个读者取消订阅,公众号就不再给当前这个读者推送文章。
1、Observer:这个接口里面就一个方法,当公众号推文时,读者通过这个方法查看文章
package observe;
/**
* 观察者模式案例
* Created by yanshao on 2019/1/4.
*/
public interface Observer {
//收到被观察者推送的主题
void update();
}
2、Subject:这三个方法分别是关注公众号、取消关注、公众号轮询推送文章的方法
package observe;
/**
* 观察者模式案例
* Created by yanshao on 2019/1/4.
*/
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void pushArticle();
}
3、WeChatSubject:微信公众号具体实现
package observe;
import java.util.ArrayList;
import java.util.Objects;
/**
* 观察者模式案例
* Created by yanshao on 2019/1/4.
*/
public class WeChatSubject implements Subject{
//推文
private String article;
//观察者对象
private ArrayList<Observer> list = new ArrayList<Observer>();
public String getArticle() {
return article;
}
public void setArticle(String article) {
this.article = article;
pushArticle();
}
/**
* 观察者注册
* */
@Override
public void registerObserver(Observer observer){
if(Objects.equals(null,observer)){
return;
}
list.add(observer);
}
/**
* 观察者取消订阅
* */
@Override
public void removeObserver(Observer observer){
if(Objects.equals(null,observer)){
return;
}
for (int i=0 ; i<list.size() ; i++){
if(list.get(i) == observer){
list.remove(i);
System.out.println(observer.getClass().getName()+",取消关注!");
break;
}
}
}
/**
* 推送文章
* */
@Override
public void pushArticle(){
list.forEach(observer -> {
observer.update();
});
}
}
4、ObserveA:读者A
package observe;
/**
* 订阅者A
* Created by yanshao on 2019/1/4.
*/
public class ObserveA implements Observer {
private WeChatSubject subject;
public ObserveA(WeChatSubject subject){
this.subject = subject;
this.subject.registerObserver(this);
}
@Override
public void update() {
System.out.println(this.getClass().getName()+",收新文章>>>"+subject.getArticle());
}
}
5、ObserveB
package observe;
/**
* 订阅者B
* Created by yanshao on 2019/1/4.
*/
public class ObserveB implements Observer {
private WeChatSubject subject;
public ObserveB(WeChatSubject subject){
this.subject = subject;
this.subject.registerObserver(this);
}
@Override
public void update() {
System.out.println(this.getClass().getName()+",收新文章>>>"+subject.getArticle());
}
}
6、ObserveC
package observe;
/**
* 订阅者C
* Created by yanshao on 2019/1/4.
*/
public class ObserveC implements Observer {
private WeChatSubject subject;
public ObserveC(WeChatSubject subject){
this.subject = subject;
this.subject.registerObserver(this);
}
@Override
public void update() {
System.out.println(this.getClass().getName()+",收新文章>>>"+subject.getArticle());
}
}
7、main方法
package observe;
/**
* Created by yanshao on 2019/1/4.
*/
public class WeChatSubscriptMain {
public static void main(String[] args) {
WeChatSubject subject = new WeChatSubject();
//用户关注微信公众号
ObserveA observeA = new ObserveA(subject);
ObserveB observeB = new ObserveB(subject);
ObserveC observeC = new ObserveC(subject);
subject.setArticle("美丽的乌克兰姑娘!");
//observeA觉得推送的文章不好看,取消订阅
subject.removeObserver(observeA);
subject.setArticle("中国,我的祖国!");
}
}
8、执行结果:
observe.ObserveA,收新文章>>>美丽的乌克兰姑娘!
observe.ObserveB,收新文章>>>美丽的乌克兰姑娘!
observe.ObserveC,收新文章>>>美丽的乌克兰姑娘!
observe.ObserveA,取消关注!
observe.ObserveB,收新文章>>>中国,我的祖国!
observe.ObserveC,收新文章>>>中国,我的祖国!
学习交流微信群: