观察者模式(Observer)又名发布-订阅(Publish/Subscribe)模式。GOF给观察者模式如下定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
在这里先讲一下面向对象设计的一个重要原则——单一职责原则。因此系统的每个对象应该将重点放在问题域中的离散抽象上。因此理想的情况下,一个对象只做一件事情。这样在开发中也就带来了诸多的好处:提供了重用性和维护性,也是进行重构的良好的基础。
观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。
例1:以手机号码为例,老师的手机号码存在学生的手机里,若老师的手机号改变,她会发一条短信通知每个学生自己手机号变了。代码如下:
package com.cn;
public interface IObserver {
public void Update();
}
package com.cn;
public interface ISubject {
// 注册观察者
public void RegisterObserver(IObserver o);
// 销毁观察者
public void RemoveObserver(IObserver o);
// 通知观察者
public void NoticeObserver();
}
package com.cn;
/**
* 学生(观察者)代码
*/
public class Student implements IObserver {
private String name;
private String phone;
private Teacher mTeacher;
public Student(String name,Teacher t){
this.name = name;
mTeacher = t;
}
public void show(){
System.out.println("name:"+name+"\n"+
"Teacher's phone:"+phone);
}
@Override
public void Update() {
// TODO Auto-generated method stub
phone = mTeacher.getPhone();
}
}
package com.cn;
import java.util.Vector;
public class Teacher implements ISubject{
private String phone;
private Vector<Student> mStudentVct;
public Teacher(){
phone = "";
mStudentVct = new Vector<Student>();
}
@Override
public void NoticeObserver() {
// TODO Auto-generated method stub
for (int i = 0; i < mStudentVct.size(); i++) {
((IObserver)mStudentVct.get(i)).Update();
}
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
NoticeObserver();
}
@Override
public void RegisterObserver(IObserver o) {
// TODO Auto-generated method stub
mStudentVct.add((Student) o);
}
@Override
public void RemoveObserver(IObserver o) {
// TODO Auto-generated method stub
mStudentVct.remove(o);
}
}
package com.cn;
import java.util.Vector;
public class Client {
public static void main(String[] args){
Vector<Student> v = new Vector<Student>();
Teacher mTeacher = new Teacher();
Student st = new Student("张三",mTeacher);
//添加学生"张三"
v.add(st);
//在老师的通讯录下加入学生"张三"
mTeacher.RegisterObserver(st);
st = new Student("李四", mTeacher);
//添加学生"李四"
v.add(st);
//在老师的通讯录下加入学生"李四"
mTeacher.RegisterObserver(st);
st = new Student("王五",mTeacher);
v.add(st);
mTeacher.RegisterObserver(st);
//设置老师的电话号码
mTeacher.setPhone("13714783148");
//通知所有的学生
for (int i = 0; i < v.size(); i++) {
((Student)v.get(i)).show();
}
//更改老师的电话号码
mTeacher.setPhone("888888");
//通知所有的学生
for (int i = 0; i < v.size(); i++) {
((Student)v.get(i)).show();
}
}
}
运行后的效果为:
资源下载地址:http://download.csdn.net/detail/niejing654092427/4582979
例子2:以汽车和驾使员为例
1、被观察者Car类,继承至Observable类
package com.cn.nj;
import java.util.Observable;
/**
* 被观察者Car类,继承至Observable类
*
*/
public class Car extends Observable implements Runnable{
private Float gasoline;//汽车的汽油量
public Car(Float gasoline) {
super();
this.gasoline = gasoline;
}
public Float getGasoline() {
return gasoline;
}
public void setGasoline(Float gasoline) {
this.gasoline = gasoline;
}
/**
* 模拟汽车行驶过程中的耗油的方法
*/
public synchronized void consume(){
if(--gasoline < 5){//若油箱中的油少于5升则让汽车提示驾驶员加油。
this.setChanged();
this.notifyObservers(gasoline);//通知驾驶员加油。
}
}
/**
* 模拟汽车的行驶过程
*/
@Override
public void run() {
while(Boolean.TRUE){
consume();
if(gasoline == 0){//当油箱中还剩0升油时汽车停止
break;
}
try {
Thread.sleep(1000);//每一秒钟耗油1升
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2、观察者Driver类,实现Observer接口
package com.cn.nj;
import java.util.Observable;
import java.util.Observer;
/**
* 观察者Driver类,实现Observer接口
*/
public class Driver implements Observer {
private String name;//驾驶员名字
public Driver(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void update(Observable observable, Object object) {
Car car = null;//当前行驶的汽车。
Float gasoline = null;//当前行驶的汽车的油量。
if(observable instanceof Car){
car = (Car)observable;
}else{
return ;
}
if(object instanceof Float){
gasoline = (Float)object;
}else{
return ;
}
if(gasoline != 0){
System.out.println("驾驶员"+name+"您好,您的油箱汽油还剩 " + gasoline + " 升,请尽快加油!" );
}else{
System.out.println("驾驶员"+name+"您好,您的油箱已无汽油,汽车已停止!" );
}
}
}
package com.cn.nj;
/**
* 测试类Test
*
*/
public class Client {
public static void main(String[] args) {
Car car = new Car(35F);//实例化被观察者,即汽车,初始状态油箱35升油。
Driver driver = new Driver("William");//实例化观察者,即汽车驾驶员,名字是William。
car.addObserver(driver);//为被观察者(汽车)添加观察者(驾驶员)
new Thread(car).start();//启动汽车行驶的线程,每一秒钟耗油1升。
}
}
运行效果如下:
代码下载地址:http://download.csdn.net/detail/niejing654092427/4582974