模式导读:
考研座位没申请到,真的烦,为什么当时接收到信息时还犹豫了那么久呢(话不多说)。观察者模式如果非要形象的表述出来差不多就像图书馆最近有什么活动然后给学生发送通知,当然学生也并非全部,只有通知相关学生,然后学生得到通知去参加这个活动。也像教务处有什么变化或者任务然后发放通知,让老师学生们根据通知做出相应的动作,这也许能叫牵一发而动全身吧,当被观察者状态发生改变时,需要通知相应的观察者,使这些观察者对象能够自动更新。
参考类图:
代码实现:
1.首先定义一个观察者接口,里面定义一个抽象的更新方法。
1 package com.etc; 2 3 public interface Observer { 4 public void update(String message); 5 }
2.定义一个被观察者的相应动作实现的接口,里面定义注册观察者,删除观察者以及通知观察者的抽象方法。
1 package com.etc; 2 3 public interface Observerable { 4 //注册观察者 5 public void resignObserver(Observer o); 6 //删除观察者 7 public void removeObserver(Observer o); 8 //遍历观察者 9 public void notifyObserver(); 10 }
3.定义一个具体的被观察者角色,实现被观察者接口,同时实现产生通知信息的方法。
1 package com.etc; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class OfficeServer implements Observerable { 7 8 private List<Observer>list; 9 public String message; 10 11 public OfficeServer(){ 12 13 list=new ArrayList<Observer>(); 14 15 } 16 17 //注册观察者(学生) 18 public void resignObserver(Observer o) { 19 list.add(o); 20 } 21 22 //删除观察者 23 public void removeObserver(Observer o) { 24 if(!list.isEmpty()) { 25 list.remove(o); 26 } 27 28 } 29 //遍历观察者并且将消息通知给所有的观察者 30 public void notifyObserver() { 31 for(int i=0;i<list.size();i++) { 32 //将每一个获取到的观察者放入集合 33 Observer observer=list.get(i); 34 observer.update(message); 35 } 36 } 37 38 //发布信息 39 public void setInformation(String str) { 40 this.message=str; 41 System.out.println("教务处最新消息:"+str); 42 //通知所有观察者 43 notifyObserver(); 44 } 45 }
4.定义一个具体观察者角色,实现观察者接口,同时实现读取通知的方法。
1 package com.etc; 2 3 public class Student implements Observer{ 4 5 public String name; 6 public String message; 7 8 //定义观察者属性(名字) 9 public Student (String name) { 10 this.name=name; 11 } 12 //获取信息并加以更新 13 public void update(String message) { 14 this.message=message; 15 read(); 16 } 17 //观察者读取被观察者的信息 18 public void read() { 19 System.out.println(name+"收到教务处信息:"+message); 20 21 } 22 }
5.情景模拟测试类。
1 package com.etc; 2 3 public class Test { 4 public static void main(String[] args) { 5 6 OfficeServer server=new OfficeServer(); 7 Observer MRzhang=new Student("张三"); 8 Observer MRli=new Student("李四"); 9 server.resignObserver(MRzhang); 10 server.resignObserver(MRli); 11 server.setInformation("考研寝室已经推出,望各位考生积极加入考研大家庭!"); 12 server.removeObserver(MRli); 13 server.setInformation("考研寝室安排就绪,考生请在一周之内搬住进入!"); 14 15 } 16 }
效果截图:
观察者模式优缺点:
优点:
1、观察者和被观察者是抽象耦合的。
2、建立一套触发机制。
缺点:
1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
适用场景:
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。