设计模式--观察者模式Demo
Observer Pattern
参考:https://www.cnblogs.com/adamjwh/p/10913660.html 学习
1、什么是观察者模式?(Observer Pattern)
1.1、定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
1.2、对于观察者模式而言,肯定有观察者和被观察者之分。比如在一个目录下建立一个文件,这时系统会通知目录管理器增加目录,并通知磁盘减少空间,在这里,文件就是观察者,目录管理器和磁盘就是被观察者。
1.3、观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新.
1.4、UML图
2、简单实现
2.1、创建Subject
public class Subject {
// 订阅者集合
private List<Observer> observerlist = new ArrayList<>();
// subject 状态
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
noticeObserver();
}
// 添加订阅者
public void addObserver(Observer observer){
observerlist.add(observer);
}
// 通知订阅者
public void noticeObserver(){
for (Observer observer : observerlist) {
observer.update();
}
}
}
2.2、Observer
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
2.3、实体观察类
public class FirstObserver extends Observer {
public FirstObserver(Subject subject){
this.subject = subject;
this.subject.addObserver(this);
}
@Override
public void update() {
System.err.println( "FirstObserver String: "
+ Integer.toBinaryString( subject.getState() ) );
}
}
public class SecondObserver extends Observer {
public SecondObserver(Subject subject){
this.subject = subject;
this.subject.addObserver(this);
}
@Override
public void update() {
System.err.println( "SecondObserver String: "
+ Integer.toOctalString( subject.getState() ) );
}
}
2.4发布通知
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
new FirstObserver(subject);
new SecondObserver(subject);
new ThirdObserver(subject);
System.out.println(" update subject state one");
subject.setState(0);
System.out.println(" update subject state two");
subject.setState(1);
}
}
2.5 输出
3、深入观察者
3.1、能解决什么问题?
- 一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
- 一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
3.2、使用场景
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
3.3、注意事项
- JAVA 中已经有了对观察者模式的支持类。
- 避免循环引用。
- 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
4、示例代码
4.1、应用场景
- 上学时老师去开会,同学们都在教师里happy,这是我们通常会派一个人去监测老师是否回来,如果回来,他通知我们,我们速速安静学习,当然有时候没有通知到,没通知到的同学被老师抓住一顿臭骂
- 分析:在上述场景中:订阅的事件时老师受否回来;在教室里玩的我们是订阅者,监视的同学是发布事件者(通知老师是否回来了),同时,老师也是发布事件者。
4.2、代码实现
-
事件抽象类
public interface Subject { /** * add 一个事件的订阅者 * @param observer */ void add(Observer observer); /** * remove一个事件的订阅者 * @param observer */ void remove(Observer observer); /** * 通知所有订阅者 */ void notice(); /** * 状态 * @param stateActionn */ void setState(String stateActionn); String state(); }
-
订阅者抽象类
public abstract class Observer { protected String name; /** * 订阅者订阅的事件 */ protected Subject subject; public Observer(String name, Subject subject) { this.name = name; this.subject = subject; } /** * 接收订阅事件的方法 */ protected abstract void update(); }
-
具体的事件类
public class SpecificSubject implements Subject { /**Subject * 存放订阅者的集合 */ private List<Observer> list = new LinkedList<Observer>(); private String statename; /** * add 一个事件的订阅者 * * @param observer */ @Override public void add(Observer observer) { list.add(observer); } /** * remove一个事件的订阅者 * * @param observer */ @Override public void remove(Observer observer) { list.remove(observer); } /** * 通知所有订阅者 */ @Override public void notice() { for (Observer observer : list) { observer.update(); } } /** * 状态 * * @param stateActionn */ @Override public void setState(String stateActionn) { this.statename = stateActionn; } @Override public String state() { return statename; } }
-
具体的订阅者1
public class ObserverOne extends Observer { public ObserverOne(String name, Subject subject) { super(name, subject); } /** * 接收订阅事件的方法 */ @Override protected void update() { System.out.println(name+","+subject.state()+",别玩了"); } }
-
具体的订阅者2
public class ObserverTwo extends Observer{ public ObserverTwo(String name, Subject subject) { super(name, subject); } /** * 接收订阅事件的方法 */ @Override protected void update() { System.out.println(name+","+subject.state()+",别看漫画了"); } }
-
具体的订阅者3
public class ObserverThree extends Observer{ public ObserverThree(String name, Subject subject) { super(name, subject); } /** * 接收订阅事件的方法 */ @Override protected void update() { System.out.println(name+","+subject.state()+"别玩手机了!"); } }
-
监视同学发布老师回来的消息
public class ClientStudent { public static void main(String[] args) { SpecificSubject subject = new SpecificSubject(); ObserverOne one = new ObserverOne("张三", subject); ObserverTwo two = new ObserverTwo("李四", subject); ObserverThree three = new ObserverThree("王五", subject); subject.add(one); subject.add(two); subject.add(three); // 李四没通知到 subject.remove(two); subject.setState("老师回来了"); subject.notice(); } }
-
输出:
-
老师发布他回来的消息
public class ClientTeacher { public static void main(String[] args) { SpecificSubject subject = new SpecificSubject(); ObserverOne one = new ObserverOne("张三", subject); ObserverTwo two = new ObserverTwo("李四", subject); ObserverThree three = new ObserverThree("王五", subject); subject.add(one); subject.add(two); subject.add(three); // 李四被老师抓住 subject.remove(one); subject.remove(three); subject.setState("想挨打吗?"); subject.notice(); } }
-
输出