观察者模式
观察者模式又叫(发布-订阅)模式,观察者通过监听某个主题,一旦主题的状态发生改变,则自动通知观察者。
类型:
行为型模式(类与类之间的行为型模式)
观察者模式中设计的角色:
- 抽象主题(Subject):定义具体主题所需的注册,删除和通知观察者的方法接口。
- 具体主题(具体被观察者):具体主题的状态发生改变时,则通知这个主题的观察者。
- 抽象观察者(Observer):得知具体主题发生改变时更新自己,通过抽象的形式,可以使得观察者和主题之间实现松耦合。
- 具体观察者:可以自主的选择与主题之间的状态,订阅主题,或者取消订阅主题。
观察者模式关系图:
观察者模式示例:
本例子是以关注博客为例,关注了博客即成为博主的粉丝,在博主更新了博客之后,会通知所有的粉丝。同时每一个具体的观察者都可以选择是否成为博主的粉丝。
抽象主题接口:
/**
* Create by zhaihongwei on 2018/3/26
* 抽象的主题对象
*/
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObserver();
}
具体的主题类
/**
* Create by zhaihongwei on 2018/3/26
* 具体的主题对象
* 我的博客类
*/
public class MyBlog implements Subject {
// 用来保存所有粉丝的容器
private ArrayList<Observer> observers = new ArrayList();
/**
* 哎呀,又有一个新的粉丝了开心。我记住你了哟!!!
* @param observer
*/
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
/**
* 555...,失去了一个粉丝,你怎么可以取消关注呢!期待与你再次相遇!
* @param observer
*/
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
/**
* 我写了一篇新的Blog,我要通知我所有的粉丝过来看。
*/
@Override
public void notifyObserver() {
// 遍历所有的粉丝,并通知他们,我更新blog了
for (Observer observer : observers) {
observer.update("亲爱的"+ observer.getClass() +",我新写了一篇blog,记得来看哦!");
}
}
}
抽象观察者接口:
/**
* Create by zhaihongwei on 2018/3/26
* 抽象观察者对象
* 通过抽象的观察对象,将主题对象和观察者对象之间实现松耦合。
*/
public interface Observer {
/**
* 更新状态
* @param newBlog
*/
void update(String newBlog);
}
具体的观察者对象:
/**
* Create by zhaihongwei on 2018/3/26
* 粉丝A
*/
public class FansA implements Observer {
@Override
public void update(String newBlog) {
System.out.println(newBlog);
}
}
/**
* Create by zhaihongwei on 2018/3/26
* 粉丝B
*/
public class FansB implements Observer {
@Override
public void update(String newBlog) {
System.out.println(newBlog);
}
}
测试类:
/**
* Create by zhaihongwei on 2018/3/26
* 测试类
*/
public class ObserverTest {
public static void main(String[] args) {
// 创建我的blog对象
Subject myBlog = new MyBlog();
// 创建粉丝对象
FansA fansA = new FansA();
FansB fansB = new FansB();
// A,B关注了我(点击了关注按钮),成为了我的粉丝
myBlog.registerObserver(fansA);
myBlog.registerObserver(fansB);
// 我写了一篇新的Blog,通知我的粉丝
myBlog.notifyObserver();
System.out.println("----------------------------------------");
// 555... FanB不再关注我了,以后我写的blog不能通知他了
myBlog.removeObserver(fansB);
// 我又写了一篇新的Blog,通知我的粉丝
myBlog.notifyObserver();
}
}
测试结果:
亲爱的class observer.FansA,我新写了一篇blog,记得来看哦!
亲爱的class observer.FansB,我新写了一篇blog,记得来看哦!
----------------------------------------
亲爱的class observer.FansA,我新写了一篇blog,记得来看哦!
总结:
通过以上示例,相信大家已经对观察者模式有所了解了,粉丝通过点击关注按钮,成为博主粉丝,博主在更新了博客之后会自动通知所有的粉丝。
问题:
我发布了博客,已经通知了粉丝,但是我突然发现写的有点小问题,我修改了一下博客,又会再通知一次我的粉丝,这样就不太友好了。可以做如下改变:
修改MyBlog类:
/**
* Create by zhaihongwei on 2018/3/26
* 具体的主题对象
* 我的博客类
*/
public class MyBlog implements Subject {
// 确认博客是否能发布,默认为false
private boolean isPublication;
// 用来保存所有粉丝的容器
private ArrayList<Observer> observers = new ArrayList();
/**
* 哎呀,又有一个新的粉丝了开心。我记住你了哟!!!
* @param observer
*/
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
/**
* 555...,失去了一个粉丝,你怎么可以取消关注呢!期待与你再次相遇!
* @param observer
*/
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
/**
* 我写了一篇新的Blog,我要通知我所有的粉丝过来看。
*/
@Override
public void notifyObserver() {
if (isPublication) {
// 遍历所有的粉丝,并通知他们,我更新blog了
for (Observer observer : observers) {
observer.update("亲爱的"+ observer.getClass() +",我新写了一篇blog,记得来看哦!");
}
}
}
public boolean setIsPublication() {
System.out.println("我已经确认博客可以发布了,快来看吧!");
isPublication=true;
return isPublication;
}
}
修改测试类:
/**
* Create by zhaihongwei on 2018/3/26
* 测试类
*/
public class ObserverTest {
public static void main(String[] args) {
// 创建我的blog对象
MyBlog myBlog = new MyBlog();
// 创建粉丝对象
FansA fansA = new FansA();
FansB fansB = new FansB();
// A,B关注了我(点击了关注按钮),成为了我的粉丝
myBlog.registerObserver(fansA);
myBlog.registerObserver(fansB);
// 我写了一篇新的Blog,并且确认博客可以发布了
myBlog.setIsPublication();
// 通知我的粉丝
myBlog.notifyObserver();
System.out.println("----------------------------------------");
// 555... FanB不再关注我了,以后我写的blog不能通知他了
myBlog.removeObserver(fansB);
// 我又写了一篇新的Blog,通知我的粉丝
myBlog.notifyObserver();
}
}
总结:
这样做之后,是否通知粉丝就变成可控的了,在我写好博客,并且确认无误后,我再去通知粉丝博客更新了,测试结果是一样的,这里没有再贴出来了。