观察者模式(Observer)

观察者模式(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



 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
观察者模式Observer是一种设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生改变时,它的所有观察者都会收到通知并且自动更新。 在这个例子中,热水器是主题对象,加热器、报警器和显示屏是观察者对象。当热水器的水温超过95度时,加热器会停止加热,报警器会开始发出语音告警,并且显示屏上会显示水温已经快烧开了。 以下是用C#实现的代码: ```csharp // 主题接口,定义了添加、删除和通知观察者的方法 public interface ISubject { void Attach(IObserver observer); void Detach(IObserver observer); void Notify(); } // 观察者接口,定义了更新的方法 public interface IObserver { void Update(ISubject subject); } // 热水器类,实现了主题接口 public class Heater : ISubject { private List<IObserver> observers = new List<IObserver>(); // 观察者列表 private int temperature; // 水温 public void Attach(IObserver observer) { observers.Add(observer); } public void Detach(IObserver observer) { observers.Remove(observer); } public void Notify() { foreach (IObserver observer in observers) { observer.Update(this); } } public void SetTemperature(int temperature) { this.temperature = temperature; Console.WriteLine("当前水温为:" + temperature + "度。"); Notify(); // 发送通知 } } // 加热器类,实现了观察者接口 public class HeaterController : IObserver { public void Update(ISubject subject) { Heater heater = (Heater)subject; if (heater != null && heater.temperature >= 95) { Console.WriteLine("加热器停止加热。"); } } } // 报警器类,实现了观察者接口 public class AlarmController : IObserver { public void Update(ISubject subject) { Heater heater = (Heater)subject; if (heater != null && heater.temperature >= 95) { Console.WriteLine("报警器开始发出语音告警。"); } } } // 显示屏类,实现了观察者接口 public class DisplayController : IObserver { public void Update(ISubject subject) { Heater heater = (Heater)subject; if (heater != null) { Console.WriteLine("液晶屏显示水温为:" + heater.temperature + "度。"); } } } // 测试代码 static void Main(string[] args) { Heater heater = new Heater(); heater.Attach(new HeaterController()); // 添加加热器观察者 heater.Attach(new AlarmController()); // 添加报警器观察者 heater.Attach(new DisplayController()); // 添加显示屏观察者 heater.SetTemperature(50); // 设置水温为50度,不会发送通知 heater.SetTemperature(90); // 设置水温为90度,不会发送通知 heater.SetTemperature(100); // 设置水温为100度,会发送通知 } ``` 输出结果如下: ``` 当前水温为:50度。 当前水温为:90度。 当前水温为:100度。 加热器停止加热。 报警器开始发出语音告警。 液晶屏显示水温为:100度。 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值