`
freewxy
  • 浏览: 336769 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

观察者模式

阅读更多

基本简介:

  观察者模式(也称为发布/订阅模式:Publish/Subscribe)是软件设计模式的一种.是对象之间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更行。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知.这通常通过呼叫各观察者所提供的方法来实现.此种模式通常被用来做事件处理系统.

  观察者模式(Observer)完美的将观察者和被观察者的对象分离开.举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上.面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面.一个对象只做一件事,并且将他做好.(单一职责原则:系统的每个对象应该将重点放在问题域中的离散抽象上。因此理想的情况下,一个对象只做一件事情。)观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性.

 

实现方法:

    观察者模式有很多实现方法,从根本上讲,该模式必须包括两个角色:观察者和被观察者.在刚才的例子中,业务数据是被观察者,用户界面是观察者.观察者和被观察者之间存在“观察”的逻辑联系,当被观察者发生改变时,观察者就会观察到这样的变化,并且做出相应的相应.如果在用户界面、业务数据之间使用这样的观察过程,可以确保界面和数据之间划清界限,假定应用程序的需求发生变化,需要修改界面的表现,只需要重新构建一个用户界面,业务数据不需要发生变化。

“观察”不是“直接调用”

实现观察者模式的时候要注意,观察者和被观察者对象之间的互动关系不能体现成类之间的直接调用,否则就将使观察者和被观察者之间紧密耦合起来,从根本上违反面向对象的设计原则。无论是观察者“观察”观察对象,还是被观察者将自己的改变“通知”观察者,都不应该直接调用。

 

实现观察者模式的过程

  实现观察者模式有很多形式:比较直观的一种是“注册-通知-撤销注册”的形式。

1、  观察者(Observer 将自己注册到被观察者对象中,被观察对象将观察者存放在一个容器里。

2、  被观察对象 被观察对象发生了某种变化,从容器中得到所有注册过的观察者,将变化通知观察者。

3、  撤销观察  观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。

观察者将自己注册到被观察者容器中时,被观察者不应该问观察者的具体类型,而是应该使用观察者的接口,这样的优点是:假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,他可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现---这一点为程序提供了更大的灵活性。

 

观察者模式的组成部分:

1、  抽象目标角色(Subject):目标角色知道它的观察者,可以有任意多个观察者观察同一个目标。并且提供注册和删除观察者对象的接口。目标角色往往由抽象类或者接口来实现。

2、  抽象观察者角色(Observer):为那些在目标发生改变时需要获得通知的对象定义一个更新接口。抽象观察者角色主要由抽象类或者接口来实现。

3、  具体目标角色(Concrete Subject:将有关状态存入各个Concrete Observer对象。当他的状态发生改变时,向它的各个观察者发出通知。

4、  具体观察者角色(Concrete Observer):存储有关状态,这些状态与目标状态保持一致。实现Observer的更新接口以使自身状态与目标的状态保持一致。在本角色内也可以维护一个指向Concrete Subject对象的引用。



 

具体例子(小孩与父母):

package wxy;

import java.util.Vector;

public class Children implements Subject{
	
	static private Vector<Observer> obs;//一个存储观察者的序列
	static private String state = null;
	static{
		obs = new Vector<Observer>();
	}
	
	


	@Override
	public void setState(String string) {
		state = string;
	}

	public static Vector<Observer> getObs() {
		return obs;
	}

	public static void setObs(Vector<Observer> obs) {
		Children.obs = obs;
	}

	public static String getState() {
		return state;
	}

	@Override
	public void attach(wxy.Observer observer) {
		obs.addElement((Observer) observer);
		
	}

	@Override
	public void detach(wxy.Observer observer) {
		obs.removeElement(observer);
		
	}

	@Override
	public void notifyObs() {
		for(Observer o :obs){
			o.update(this);
		}
	}

}

 

package wxy;
//观察者
public interface Observer {
	public void update(Children child);
}

 

package wxy;

public class Mother implements Observer{

	@Override
	public void update(Children child) {
		if(child.getState().equals("fight")){
			System.out.println("告诉妈妈,他和别人打架了");
		}else if(child.getState().equals("scholarship")){
			System.out.println("告诉妈妈,他得到了奖学金");
		}
	}

}

 

package wxy;

public class Father implements Observer{

	@Override
	public void update(Children child) {
		if(child.getState().equals("fight")){
			System.out.println("告诉爸爸,他和别人打架了");
		}else if(child.getState().equals("scholarship")){
			System.out.println("告诉爸爸,他得到了奖学金");
		}
	}

}

 

package wxy;

public class Client {

	/**
	 * 测试类
	 * @param args
	 */
	public static void main(String[] args) {
		Subject child = new Children();
		Observer father = new  Father();
		Observer mother = new Mother();
		
		child.attach(father);
		child.attach(mother);
		
		child.setState("fight");
		child.notifyObs();
		child.setState("scholarship");
        child.notifyObs();
	}

}

  

 

 

 

JDK提供了对observer设计模式的支持:
- 通过java.util.Observable类扮演Subject角色,

  一个类只需通过继承java.util.Observable类便可担当ConcreteSubject角色;

- java.util.Observable的实现类通过调用setChanged()方法以及notifyObservers(Object)方法便可简单地通知Observer。
- 通过java.util.Observer接口扮演Observer角色,

  一个类只需实现java.util.Observer接口便可担当ConcreteObserver角色。

 

package wxy.JDK;

import java.util.Observable;
import java.util.Vector;

/**
 * 孩子,被观察者
 * 通过java.util.Observable类扮演Subject角色,
 * 该类通过继承Obsevable类担当ConcreteSubject对象
 * @author wxy
 *
 */
public class Children extends Observable{
	String state;

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
		
		setChanged();//通过setChanged()方法表明对象的状态已经改变
		this.notifyObservers(state);//通知各Observer,并发送对象的消息
	}

}

 

package wxy.JDK;

import java.util.Observable;
import java.util.Observer;

public class Father implements Observer{

	@Override
	public void update(Observable o, Object arg) {
		if(((Children)o).getState().equals("fight")){
			System.out.println("告诉爸爸,他和别人打架了");
		}else if(((Children)o).getState().equals("scholarship")){
			System.out.println("告诉爸爸,他得到了奖学金");
		}
	}



}

 

package wxy.JDK;

import java.util.Observable;
import java.util.Observer;
/**
 * 通过java.util.Observer接口扮演Observer角色,
 * 该类实现java.util.Observer接口担当ConcreteObserver角色
 * @author wxy
 *
 */
public class Mother implements Observer{
	
	@Override
	public void update(Observable o, Object arg) {
		if(((Children)o).getState().equals("fight")){
			System.out.println("告诉妈妈,他和别人打架了");
		}else if(((Children)o).getState().equals("scholarship")){
			System.out.println("告诉妈妈,他得到了奖学金");
		}
	}

}

 

package wxy.JDK;

public class Client {

	/**
	 * 测试类
	 * @param args
	 */
	public static void main(String[] args) {
		Children child = new Children();
		
		//添加观察者对象
		child.addObserver(new Mother());
		child.addObserver(new Father());
		
		//触发通知事件
		child.setState("fight");
		child.setState("scholarship");
	}

}

 

测试结果

告诉爸爸,他和别人打架了
告诉妈妈,他和别人打架了
告诉爸爸,他得到了奖学金
告诉妈妈,他得到了奖学金

 

  • 大小: 24.1 KB
2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics