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

设计模式:观察者模式

阅读更多
        观察者模式是一种常用的依赖之间松耦合的设计模式,又叫发布-订阅(Publish/Subscribe)模式或监听模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象——被监听者——在状态上发生变化时,会通知所有观察者对象(监听者),使它们能够自动更新自己。
        在平常的生活中,很多人都喜欢听单田芳老爷子讲的评书,通常是在每天12:30开讲,这时候喜欢评书的听众会把收音机调到某个有单老爷子评书的频道,就可以收听自己喜欢的评书了。造这个示例中,有单老爷子评书的频道就是一个主题,而听众就是观察者,而观察者将收音机频道调到评书的的频道的动作就是注册事件。
        在观察者模式中,又分为推模型和拉模型两种方式。
      ●推模型
     主题对象向观察者推送主题的详细信息,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据。
      ●拉模型
     主题对象在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到主题对象
        观察者模式的优点:
            ●支持松耦合和减少依赖性。客户端不再依赖于观察器,因为通过使用主体和 Observer 接口对客户端进行了隔离。许多框架具有此优点,在这些框架中的应用程序组件可以注册为当(低级)框架事件发生时得到通知。结果,框架将调用应用程序组件,但不会依赖于它。
            ●观察器数目可变。观察器可以在运行时附加和分离,因为主体对于观察器数目没有任何假定。此功能在这样的情况下是很有用的:观察器数在设计时是未知的。例如,如果用户在应用程序中打开的每个窗口都需要一个观察器。
        我们本节主要讲基于“推模型”的观察者模式。
        下面我们来看一下观察者模式的类图:

         Subject角色:可以是一个接口或抽象类,主题角色把所有的观察者对象的引用保存在一个列表里;每个主题都可以有任何数量的观察者。主题提供一个接口可以加上或撤销观察者对象;主题角色又叫做抽象被观察者(Observable)角色;
         Observer角色:为所有的具体观察者定义一个接口,在得到通知时更新自己;
         ConcreteSubject角色:具体主题,保存对具体观察者对象有用的内部状态;在这种内部状态改变时给其观察者发出一个通知;具体主题角色又叫作具体被观察者角色;
         ConcreteObserver角色:具体观察者,保存一个指向具体主题对象的引用;和一个与主题的状态相符的状态。具体观察者角色实现抽象观察者角色所要求的更新自己的接口,以便使本身的状态与主题的状态自恰。
         下面我们再来看一下具体的代码:
package org.pattern.observer;

/**
 * 主题接口
 * @author JackyChen
 *
 */
public interface ISubject {
	
	/**
	 * 注册观察者
	 * @param observer 观察者
	 */
	void attach(IObserver observer);
	
	/**
	 * 删除观察者
	 * @param observer 观察者
	 */
	void detach(IObserver observer);
	
	/**
	 * 给所有观察者发信息
	 */
	void notifyObservers();

}
         

        
package org.pattern.observer;

/**
 * 观察者接口
 * @author JackyChen
 *
 */
public interface IObserver {
	
	void update(String msg);

}
         

        
package org.pattern.observer;

/**
 * 具体观察者
 * @author JackyChen
 *
 */
public class ConcreteObserver implements IObserver {

	/**
	 * @param msg 从主题接收到的信息
	 */
	public void update(String msg) {
		System.out.println("Observer(" + this.hashCode() + ") 接收到了:" + msg);
		//具体逻辑由用户决定...
	}

}
         

        
package org.pattern.observer;

import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 具体主题
 * @author JackyChen
 *
 */
public class ConcreteSubject implements ISubject {
	
	private Vector<IObserver> observersVector = new Vector<IObserver>();
	/**
	 * Executors.newFixedThreadPool线程池线程数,由服务器可用的CPU核心数量决定
	 */
	private static final int numThread = Runtime.getRuntime().availableProcessors()
;

	@Override
	public void attach(IObserver observer) {
		observersVector.add(observer);
	}

	@Override
	public void detach(IObserver observer) {
		observersVector.remove(observer);
	}

	@Override
	public void notifyObservers() {
		//这个方法会有一些问题,由于是在ConcreteSubject线程内遍历观察者列表,
		//故如果某一个观察者爆了异常的话,其他的观察者就不会被调用,可以改为
		//由多线程来对每一个观察者的调用
		/**
		 * for(IObserver observer : observersVector){		 
		 *	 observer.update(this.hashCode() + " 状态变了。");
		 * }
		 */
		ExecutorService exec = Executors.newFixedThreadPool(numThread);
		for(final IObserver observer : observersVector){
			exec.execute(new Runnable(){
				@Override
				public void run() {
					observer.update("状态变了。");
				}
				
			});
		}
		exec.shutdown();
	}

}
         
  • 大小: 7 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics