`
clq9761
  • 浏览: 589128 次
  • 性别: Icon_minigender_1
  • 来自: 福建
社区版块
存档分类
最新评论

观察者模式

阅读更多

  观察者模式(发布-订阅模式):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
                  这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
  
  当一个对象的改变需同时改变其它对象的时候,而且它不知道具体有多少对象有待改变时,应考虑使用观察者模式。
                    
 优点:
  第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,
          每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们
          都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。 
          如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。 
  第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知.
 
 缺点:
   第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
   第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。
            在使用观察者模式是要特别注意这一点。 
   第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
   第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使
           观察者知道所观察的对象是怎么发生变化的。 
   第五、抽象通知者依赖于抽象观察者,没有抽象观察者的接口,通知功能就完成不了。另外就是每个具体
            的观察者不一定是更新的方法update()要调用。

 

 

/**
 * 抽象观察者:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
 * 抽象观察者一般用一个抽象类或者一个接口实现,通常包含一个更新方法update()。
 * 
 */
public abstract class Observer {
	
	public abstract void update();
	
}

 

/**
 * 具体观察者:实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。
 * 			 具体观察者角色可以保存一个指向具体主题对象的引用。
 */
public class ConcreteObserver extends Observer {
	
	private String name;
	private String observerState;
	private ConcreteSubject subject;	
	public ConcreteObserver(String name,ConcreteSubject subject){
		this.name = name;
		this.subject = subject;
	}
	@Override
	public void update() {		
		this.observerState = subject.getSubjectState();		
		System.out.println("观察者"+name+"的新状态是"+observerState);
	}

	public ConcreteSubject getSubject() {
		return subject;
	}

	public void setSubject(ConcreteSubject subject) {
		this.subject = subject;
	}
}

 

/**
 * 主题或抽象通知者:一般用一个抽象类或一个接口实现,把所有对观察者对象的引用保存在一个聚集里,
 * 		每个主题都可以有任何数量的观察者,可以增加或删除观察者对象。
 */
public abstract class Subject {
	
	private List<Observer> observerList = new ArrayList<Observer>();
	
	//增加观察者
	public void attach(Observer observer){
		observerList.add(observer);	
	}
	// 移除观察者
	public void remove(Observer observer){
		observerList.remove(observer);
	}	
	// 通知
	public void notice(){		
		for(Observer observer:observerList){
			observer.update();
		}		
	}
}

 

/**
 * 具体的主题或具体的通知者:将有关状态存入具体的观察者对象,在具体主题的内部状态改变时,
 * 		          给所有登记过的观察者发出通知。
 */
public class ConcreteSubject extends Subject {

	// 具体被观察者的状态
	private String subjectState;

	public String getSubjectState() {
		return subjectState;
	}

	public void setSubjectState(String subjectState) {
		this.subjectState = subjectState;
	}
}

 

public class Main {

	public static void main(String[] args) {
		
		// 主题对象(被观察者)
		ConcreteSubject subject = new ConcreteSubject();
		// 添加观察者对象
		subject.attach(new ConcreteObserver("X",subject));
		subject.attach(new ConcreteObserver("Y",subject));
		subject.attach(new ConcreteObserver("Z",subject));		
		// 主题对象状态更新
		subject.setSubjectState("ABC");		
		// 发出通知
		subject.notice();
	}
}

 

 

观察者模式实例:(老板-同事)

 

 

/**
 * 抽象观察者
 *
 */
public abstract class Observer {
	
	protected String name;
	
	// 对通知者的引用
	protected Subject subject;
	
	public Observer(String name,Subject subject){
		this.name = name;
		this.subject = subject ;
	}	
	// 抽象更新方法
	public abstract void update();
}

 

/**
 * 看NBA的同事:具体的观察者,实现观察者抽象类
 *
 */
public class NBAObserver extends Observer {

	public NBAObserver(String name, Subject subject) {
		super(name, subject);
	}

	@Override
	public void update() {
		System.out.println(subject.getSubjectState()
				    +" "+name+"关闭NBA直播,继继工作");
	}
}

 

/**
 * 看股票的同事:具体的观察者,实现观察者抽象类
 *
 */
public class StockObserver extends Observer {

	public StockObserver(String name, Subject subject) {
		super(name, subject);
	}

	@Override
	public void update() {
		System.out.println(subject.getSubjectState()
				    +" "+name+"关闭股票行情,继继工作");
	}
}

 

/**
 * 通知者接口
 */
public interface Subject {	
	
	// 添加观察者
	public void attach(Observer observer);
	public void remove(Observer observer);
	
	// 通知者的状态
	public String getSubjectState();
	public void setSubjectState(String subjectState);
	
	// 发出通知
	public void notice();
}

 

/**
 * 老板:具体的通知者类,实现通知者接口
 */
import java.util.ArrayList;
import java.util.List;
public class Boss implements Subject {	
	
	// 通知者的状态
	private String subjectState;
	
	// 观察者的聚集
	private List<Observer> observerList = new ArrayList<Observer>();

	public void attach(Observer observer) {
		observerList.add(observer);
	}
	public String getSubjectState() {
		return subjectState;
	}
	public void remove(Observer observer) {
		observerList.remove(observer);
	}
	public void setSubjectState(String subjectState) {
		this.subjectState = subjectState;
	}
	// 发出通知
	public void notice() {
		for(Observer observer:observerList){
			observer.update();
		}		
	}
}

 

public class Main {

	public static void main(String[] args) {
		
		// 老板胡汉三
		Boss huhansan = new Boss();		
		// 看股票的同事
		StockObserver tongshi1 = new StockObserver("小王",huhansan);		
		// 看NBA的同事
		NBAObserver tongshi2 = new NBAObserver("小李",huhansan);
		
		huhansan.attach(tongshi1);
		huhansan.attach(tongshi2);
		
		// 小李没有被老板通知到,所以移去
		huhansan.remove(tongshi2);
		
		// 老板回来了
		huhansan.setSubjectState("我胡汉三回来了");
		
		// 发出通知
		huhansan.notice();
	}
}

 

运行结果如下:

 

我胡汉三回来了 小王关闭股票行情,继继工作

 

 

 观察者模式改进:利用委托机制对抽象通知者与抽象观察者依赖的解藕, 可指定不同的通知对象

                           和通知时调用不同的方法。

 

/**
 * 看NBA的同事:具体的观察者
 *
 */
public class NBAObserver {
	
	public void closeNBADirectSeeding(Date date) {
		System.out.println("关闭NBA直播,继继工作"+date);
	}
}

 

/**
 * 看股票的同事:具体的观察者
 *
 */
public class StockObserver{
	
	public void closeStockMarket(String name) {
		System.out.println("关闭股票行情,继继工作"+name);
	}
}

 

/**
 * 事件类
 */
public class Event {
	
	// 要执行方法的对象
	private Object object;
	// 要执行方法的名称
	private String methodName;
	// 要执行方法的参数
	private Object[] params;
	// 要执行方法的参数类型
	private Class[] paramTypes;
	
	public Event(){		
	}
	public Event(Object object,String methodName,Object... args){
		this.object = object;
		this.methodName = methodName;
		this.params = args;
		this.contractParamTypes(params);
	}
	
	// 根据参数数组生成参数类型数组
	private void contractParamTypes(Object[] params){
		this.paramTypes = new Class[params.length];
		for(int i=0;i<params.length;i++){
			// 参数类型
			this.paramTypes[i] = params[i].getClass();
		}		
	}
	
	// 执行该对象的该方法
	public void invoke() throws Exception{
		
		Method method = object.getClass().getMethod(this.getMethodName(),
						this.getParamTypes());
		if(method==null){
			return;
		}
		method.invoke(this.getObject(), this.getParams());		
	}	
	
	public Object getObject() {
		return object;
	}
	public void setObject(Object object) {
		this.object = object;
	}
	public String getMethodName() {
		return methodName;
	}
	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}
	public Object[] getParams() {
		return params;
	}
	public void setParams(Object[] params) {
		this.params = params;
	}
	public Class[] getParamTypes() {
		return paramTypes;
	}
	public void setParamTypes(Class[] paramTypes) {
		this.paramTypes = paramTypes;
	}
}

 

/**
 * 若干Event类的载体,同时提供一个所有执行Event类的方法
 *
 */
public class EventHandler {
	
	private List<Event> objects;
	
	public EventHandler(){
		objects = new ArrayList<Event>();
	}
	
	// 添加某个对象要执行的事件,及需要的参数
	public void addEvent(Object object,String methodName,Object... args){
		objects.add(new Event(object,methodName,args));
	}
	
	// 通知所有的对象执行指定的事件
	public void notice() throws Exception{
		for(Event event:objects){
			event.invoke();
		}
	}
}

 

/**
 * 抽象通知者
 *
 */
public abstract class Subject {
	
	private EventHandler eventHandler = new EventHandler();
	
	// 添加观察者
	public abstract void addListener(Object object,
					     String methodName,Object... args);
	
	// 通知所有观察者
	public abstract void notice();

	public EventHandler getEventHandler() {
		return eventHandler;
	}
	public void setEventHandler(EventHandler eventHandler) {
		this.eventHandler = eventHandler;
	}
}

 

/**
 * 老板:具体的通知者类,实现通知者接口
 */
public class Boss extends Subject{

	@Override
	public void addListener(Object object, String methodName, Object... args) {		
		// 添加观察者对象
		this.getEventHandler().addEvent(object, methodName, args);
	}
	
	@Override
	public void notice() {		
		try {			
			// 对所有观察者发出通知
			System.out.println("老板回来了");
			this.getEventHandler().notice();
		} catch (Exception e) {			
			e.printStackTrace();
		}		
	}
}

 

/**
 * 观察者模式实例:利用委托机制对抽象通知者与抽象观察者依赖的解藕。
 * 				可指定不同的通知对象和通知时调用不同的方法。
 */
public class Main {

	public static void main(String[] args) {
		
		// 老板(也可以是前台放哨人)
		Boss boss = new Boss();
		
		// 看NBA的同事
		NBAObserver tongshi1 = new NBAObserver();
		// 看股票的同事
		StockObserver tongshi2 = new StockObserver();
		
		// 添加被通知的对象
		boss.addListener(tongshi1, "closeNBADirectSeeding", new Date());
		boss.addListener(tongshi2, "closeStockMarket", "Test");
		
		// 发出通知
		boss.notice();
	}
}

 

运行结果如下:

 

老板回来了
关闭NBA直播,继继工作Fri Jun 17 02:44:48 GMT 2011
关闭股票行情,继继工作Test

 

  • 大小: 35.6 KB
  • 大小: 26.5 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics