观察者模式

什么是观察者模式?

定义对象间的一种一对多依赖关系使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。

简单举例:

  • 问题: 假设猫是老鼠和狗的观察目标,老鼠和狗是观察者,猫叫老鼠和狗也有相应的反应,使用观察者模式描述该过程。
  • 分析:
  1. 写一个抽象的猫类,作为被观察者,也就是观察目标,你的一举一动要被观察你的东西知道,他们如何知道呢?这就需要你的通知。所以每一个观察者都要在你这里注册一下才能给他们通知。
  2. 观察者观察的就是你的一举一动,也就是你的状态,你要有得到状态的方法,方便他们知道。
  3. 要有一个抽象观察者类,抽象的更新方法。
  4. 具体实现观察者类时不妨把观察目标传进来,以便得到他们的状态。
  • 图示:
    观察者模式
  • 代码:
package guanchazhemoshi;
public abstract class Cat {
	public abstract void add(Observer observer);
	public abstract void remove(Observer observer);
	public abstract void miao(int sound);
}
package guanchazhemoshi;
public interface Observer {
	public abstract void update();
}

package guanchazhemoshi;
public class State {
	String s;
	public State(int sound) {
		if(sound==1){s="好饿";}
		else if(sound==2){s="无聊";}
		else if(sound==3){s="生气";}
	}
	public String gets(){
		return s;
	}
}

package guanchazhemoshi;
public class Mouse implements Observer{
	private TomCat cat;
	Mouse(TomCat cat){
		this.cat = cat;
	}
	public void update(){
		String s = cat.getState().gets();
		if(s=="好饿"){
			System.out.println("老鼠:那只猫又饿了,我得藏起来");
		}
		if(s=="无聊"){System.out.println("老鼠:呵呵");}
		if(s=="生气"){System.out.println("老鼠:哈哈,傻猫,气死你");}
	}
}

package guanchazhemoshi;

public class Dog implements Observer{
	private TomCat cat;
	Dog(TomCat cat){
		this.cat = cat;
	}
	public void update(){
		String s = cat.getState().gets();
		if(s=="好饿"){
			System.out.println("狗:懒猫,饿死你");
		}
		if(s=="无聊"){System.out.println("狗:无聊去抓老鼠呀");}
		if(s=="生气"){System.out.println("狗:不敢惹,离你远点");}
	}
}


package guanchazhemoshi;

import java.util.ArrayList;

public class TomCat extends Cat {
	ArrayList<Observer> list = new ArrayList<Observer>();
	State state;
	/*
	 * 注册观察者
	 */
	public void add(Observer observer) {
		list.add(observer);
	}
	/*
	 * 删除观察者
	 */
	public void remove(Observer observer) {
		list.remove(observer);
	}
	/*
	 * 不同的猫叫声大小代表不同的状态,以此通知观察者
	 */
	public void miao(int sound) {
		this.setState(sound);
		for(Observer observer:list){
			observer.update();
		}
	}
	/*
	 * 根据声音大小设置状态
	 */
	public void setState(int sound){
		state = new State(sound);
	}
	/*
	 * 得到当前状态
	 */
	public State getState(){
		return state;
	}
}

package guanchazhemoshi;

public class Client {
	
	public static void main(String[] args) {
		TomCat c = new TomCat();
		Mouse m = new Mouse(c);
		Dog d =  new Dog(c);
		c.add(m);
		c.add(d);
		c.miao(1);
		c.miao(2);
		c.miao(3);	
	}
}

老鼠:那只猫又饿了,我得藏起来
狗:懒猫,饿死你
老鼠:呵呵
狗:无聊去抓老鼠呀
老鼠:哈哈,傻猫,气死你
狗:不敢惹,离你远点