设计模式 (十五)观察者模式(Observer)

观察者模式(Observer)就是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都得到通知并被自动更新。

对于观察者模式的原理图:


 通过一个一个抽象的主题Subject保存了多个信息处理列表,可以添加多个观察者,实现即时的通知观察者最新动态然后分别派生子类对象对具体的消息和状态做出处理,下面我们联系到具体的问题:正好我还在读,就拿学校通知公告来举例子吧,学校发布一个公告,要通知学生,老师,保洁阿姨,和食堂等相应的通知,这样才能正常的进行工作,比如这次清明放假,要通知所有机关和单位做好准备,这样才能保证正常有序的进行,下面是简单的原理图和例子程序:

换了一个UML这次用的一个jude很好的简单实用,而且这个是免安装的

提供了一下下载地址

http://download.csdn.net/detail/wclxyn/4226796(不需要财富值)

示例原理图(新手原理图不对之处请多多指教)

首先定义接口观察者,定义接受消息的方法,具体内容如下:

[java]  view plain copy
  1. package com.designpattern.observer;  
  2.   
  3. public interface Observer {  
  4.     public void receive(String message);  
  5. }  
然后分别写教师,学生,食堂,保洁观察者的实现类:

[java]  view plain copy
  1. package com.designpattern.observer;  
  2.   
  3. public class Teachers implements Observer {  
  4.   
  5.     @Override  
  6.     public void receive(String message) {  
  7.         System.out.println("教师收到" + message);  
  8.     }  
  9.   
  10. }  

[java]  view plain copy
  1. package com.designpattern.observer;  
  2.   
  3. public class Students implements Observer {  
  4.   
  5.     @Override  
  6.     public void receive(String message) {  
  7.         System.out.println("学生收到" + message);  
  8.     }  
  9.   
  10. }  

[java]  view plain copy
  1. package com.designpattern.observer;  
  2.   
  3. public class Mess implements Observer {  
  4.   
  5.     @Override  
  6.     public void receive(String message) {  
  7.         System.out.println("食堂收到" + message);  
  8.     }  
  9.   
  10. }  

[java]  view plain copy
  1. package com.designpattern.observer;  
  2.   
  3. public class Cleaner implements Observer {  
  4.   
  5.     @Override  
  6.     public void receive(String message) {  
  7.         System.out.println("保洁收到" + message);  
  8.     }  
  9.   
  10. }  

然后定义被观察者接口,具体这里是学校,定义了通知公告的方法announcement方法和提醒方法notifyReceive方法同时定义add和romove观察者的方法,这里用synchronized控制添加和移除,为了操作的便捷,定义返回值为School,这样能连续操作,如下:

[java]  view plain copy
  1. office.addObserver(new Mess()).addObserver(new Students()).addObserver(  
  2.                 new Teachers()).addObserver(new Cleaner());  
具体的School如下:

[java]  view plain copy
  1. package com.designpattern.observer;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. public abstract class School {  
  7.   
  8.     private List<Observer> observers = new ArrayList<Observer>();  
  9.     private String message;  
  10.   
  11.     public String getMessage() {  
  12.         return message;  
  13.     }  
  14.   
  15.     public void setMessage(String message) {  
  16.         this.message = message;  
  17.     }  
  18.   
  19.     public void announcement() {  
  20.         notifyRecevie();  
  21.     }  
  22.   
  23.     public synchronized School addObserver(Observer observer) {  
  24.         observers.add(observer);  
  25.         return this;  
  26.     }  
  27.   
  28.     public synchronized School removeObserver(Observer observer) {  
  29.         observers.remove(observer);  
  30.         return this;  
  31.     }  
  32.   
  33.     public void notifyRecevie() {  
  34.         for (int i = 0; i < observers.size(); i++) {  
  35.             Observer observer = (Observer) observers.get(i);  
  36.             observer.receive(getMessage());  
  37.         }  
  38.     }  
  39. }  

然后具体的实例类Office进行具体的通知:

[java]  view plain copy
  1. package com.designpattern.observer;  
  2.   
  3. public class Office extends School {  
  4.     @Override  
  5.     public void announcement() {  
  6.         System.out.println("政教处通知明天放假");  
  7.         this.setMessage("明天放假");  
  8.         super.announcement();  
  9.         System.out.println("---------------------");  
  10.     }  
  11. }  

之后客户端调用:

[java]  view plain copy
  1. package com.designpattern.observer;  
  2.   
  3. public class Client {  
  4.     public static void main(String[] args) {  
  5.         Office office = new Office();  
  6.         office.addObserver(new Mess()).addObserver(new Students()).addObserver(  
  7.                 new Teachers()).addObserver(new Cleaner());  
  8.         office.announcement();  
  9.     }  
  10. }  

然后打印结果如下,如果动态的添加和移除观察者都能实现通知:

[html]  view plain copy
  1. 政教处通知明天放假  
  2. 食堂收到明天放假  
  3. 学生收到明天放假  
  4. 教师收到明天放假  
  5. 保洁收到明天放假  
  6. ---------------------  
在java的API里面也封装好了这样一个观察者的接口

具体的实例时观察者继承Observer类,被观察者实现Observable接口然后调用其中的具体方法,操作很简单具体参见API就可以了,简单些了一个小Demo:

[java]  view plain copy
  1. package wlzx.mh.observer;  
  2.   
  3. import java.util.Observable;  
  4.   
  5. public class House extends Observable {  
  6.     private float price;  
  7.     private String name;  
  8.   
  9.     public String getName() {  
  10.         return name;  
  11.     }  
  12.   
  13.     public House(float price) {  
  14.         this.price = price;  
  15.     }  
  16.       
  17.     public String toString(){  
  18.         return "House.java" ;  
  19.     }  
  20.     public float getPrice() {  
  21.         return price;  
  22.     }  
  23.       
  24.     public void setName(String name) {  
  25.         this.name = name;  
  26.         super.setChanged();  
  27.         super.notifyObservers(name);  
  28.     }  
  29.     public void setPrice(float price) {  
  30.         super.setChanged();// 通知内容已经可以被修改了  
  31.         this.price = price;  
  32.         // 一旦修改,则表示价格改变,那么价格改变之后,实际上应该立刻通知所有的观察者  
  33.         super.notifyObservers(price);// 通知所有的观察者已经改变  
  34.     }  
  35. }  

[java]  view plain copy
  1. package wlzx.mh.observer;  
  2.   
  3. import java.text.SimpleDateFormat;  
  4. import java.util.Date;  
  5. import java.util.Observable;  
  6. import java.util.Observer;  
  7.   
  8. public class Person implements Observer {  
  9.   
  10.     // arg表示改变之后的内容  
  11.     // o表示观察的对象  
  12.   
  13.     public String getDateTime() {  
  14.         return (new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS")  
  15.                 .format(new Date())).toString();  
  16.     }  
  17.   
  18.     public void update(Observable o, Object arg) {  
  19.         System.out.println(getDateTime() + "----" + o + "----" + arg);  
  20.     }  
  21.   
  22. }  

[java]  view plain copy
  1. package wlzx.mh.observer;  
  2.   
  3. public class TestObserver {  
  4.     public static void main(String[] args) {  
  5.         House h = new House(3000.0f);  
  6.         Person per1 = new Person();  
  7.         Person per2 = new Person();  
  8.         Person per3 = new Person();  
  9.         h.addObserver(per1);// 增加一个观察者  
  10.         h.addObserver(per2);// 增加一个观察者  
  11.         h.addObserver(per3);// 增加一个观察者  
  12.         h.setPrice(6000.0f);// 要通知观察者内容已经被改变了  
  13.         h.setName("wclxyn");  
  14.     }  
  15.   
  16. }  

[html]  view plain copy
  1. 2012-04-14 11:44:30.578----House.java----6000.0  
  2. 2012-04-14 11:44:30.578----House.java----6000.0  
  3. 2012-04-14 11:44:30.578----House.java----6000.0  
  4. 2012-04-14 11:44:30.578----House.java----wclxyn  
  5. 2012-04-14 11:44:30.578----House.java----wclxyn  
  6. 2012-04-14 11:44:30.578----House.java----wclxyn  

这样具体的内容改变都会被监控了。

观察者模式在被观察者和观察者之间建立一个抽象的耦合,每一个具体的观察者都符合一个抽象观察者的接口,被观察者并不知道任何一个具体的观察者,他只知道他们有一个共同的接口,从而使得被观察者和观察者耦合度降低,而且观察者模式支持广播通信。被观察者会向所有注册过的观察者发出通知,但是如果一个被观察者有N个观察者那么在通知过程种会耗费大量的时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值