设计模式学习笔记十一:观察者模式
介绍
观察者(observer)模式也叫发布-订阅模式,实现了观察者和被观察者的解耦操作,观察者可以根据自身需求选择关注哪些主题和取消关注哪些主题,当主题发生变化的时候会轮询通知观察者,所以主题和观察者之间是一对多的关系。
典型应用
- MQ
- AWT事件监听
- NIO多路复用
- ……
UML结构图:
代码实现:
1.主题接口
package com.array7.observer;
public interface Subject<T> {
/**
* 创建观察者
* @param observer
*/
public void add(Observer<T> observer);
/**
* 删除观察者
* @param observer
*/
public void remove(Observer<T> observer);
/**
* 轮询通知观察或者
*/
public void notifyObservers();
}
2.具体主题实现
package com.array7.observer;
import java.util.HashSet;
import java.util.Set;
/**
* 具体的主题,即被观察者
*/
public class ConcrectSubject implements Subject<String> {
private Set<Observer<String>> observers;
private String changeData;
public ConcrectSubject() {
observers = new HashSet<Observer<String>>();
}
@Override
public void add(Observer<String> observer) {
observers.add(observer);
}
@Override
public void remove(Observer<String> observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer<String> observer : observers) {
observer.update(this.getChangeData());
}
}
public String getChangeData() {
return changeData;
}
/**
* 触发update操作的方法
*/
public void setChangeData(String changeData) {
this.changeData = changeData;
notifyObservers();
}
}
3.观察者接口
package com.array7.observer;
/**
* 观察者接口
* @param <T>
*/
public interface Observer<T> {
/**
* 状态更新通知
* @param t
*/
public void update(T t);
/**
* 主题已经存在了一个remove(..)方法,依然可以提供一个取消订阅的方法(可选)
* 为了区分这里名称定义为了quit()
*/
public void quit();
}
4.具体观察者实现
package com.array7.observer;
/**
* 具体的观察者
*/
public class ConcrectObserver implements Observer<String>, BizService<String> {
private Subject<String> subject;
public ConcrectObserver(Subject<String> subject) {
subject.add(this);
this.subject = subject;
}
@Override
public void update(String str) {
// logic
dosmth(str);
}
@Override
public void dosmth(String str) {
System.out.println(Thread.currentThread().getName() + ":" + str);
}
@Override
public void quit() {
subject.remove(this);
}
}
5.其他业务逻辑组合
package com.array7.observer;
/**
* 强制在观察者具体实现类实现此方法
*/
public interface BizService<T> {
public void dosmth(T t);
}
6.Run
package com.array7.observer;
/**
* 运行类
*/
public class Run {
public static void main(String[] args) {
ConcrectSubject subject = new ConcrectSubject();
// 初始化一个观察者
new ConcrectObserver(subject);
subject.setChangeData("abcd");
subject.setChangeData("1234");
ConcrectObserver tmpObserver = new ConcrectObserver(subject);
subject.setChangeData("dcba");
// 删除这个观察者
subject.remove(tmpObserver);
// 新加入的观察者,我们预计会输出两次4321 :]
new ConcrectObserver(subject);
subject.setChangeData("4321");
}
}
TIPS
在JDK中也提供的观察者模式的实现,但是JDK中的观察者接口是使用抽象类实现的。这就意味着如果想使用JDK中自带的实现,就不能再继承其他的基类了。而如果在基类继承,代码耦合度又会上来,因为可能不是所有的类都需要使用观察者。能用接口,尽量不用继承,也是设计原则之一:多用组合,少用继承。
版权声明:本文为博主原创文章,未经博主允许不得转载。