观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有的观察者对象,让他们可以自动更新自己。

观察者模式的类图:


  • 抽象主题(Subject):主题对象可以把所有的观察者对象保存在一个容器中,并且抽象主题提供删除和注册观察者的方法。
  • 抽象观察者(Observer):是所有具体的观察者的接口,在得到抽象主题发生变化时更新自己的状态。
  • 具体主题(ConcreteSubject):在具体主题的内部状态发生变化时,给所有登记过的观察者发出通知。
  • 具体观察者(ConcreteObserver):存储于主题相符的状态,具体观察者实现抽象观察者的更新方法。
抽象主题:
public interface Subject {

	//注册观察者
	public void attach(Observer observer);
	
	//移除观察者
	public void remove(Observer observer);
	
	//通知所有观察者已经更新状态
	void notifyAllObserver();
}
具体主题:
public class ConcreteSubject implements Subject {

	private int state;

	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
		// 主题状态改变,通知所有观察者
		this.notifyAllObserver();
	}

	// 使用ArrayList管理观察者
	private ArrayList<Observer> list = new ArrayList<Observer>();

	@Override
	public void attach(Observer observer) {
		list.add(observer);
	}

	@Override
	public void remove(Observer observer) {
		list.remove(observer);
	}

	@Override
	public void notifyAllObserver() {
		// 通知所有观察者
		for (Observer o : list) {
			o.update(this);
		}
	}
}
抽象观察者:
public interface Observer {

	// 更新状态
	public void update(Subject subject);
}
具体观察者:
public class ConcreteObserver implements Observer {

	private int myState;

	private String myName;

	public ConcreteObserver(String _name) {
		this.myName = _name;
	}

	@Override
	public void update(Subject subject) {

		// 得到状态
		myState = ((ConcreteSubject) subject).getState();
		System.out.println("观察者: " + this.myName + ":--->" + myState);
	}

}
客户端类:
public class Client {

	public static void main(String[] args) {

		// 得到具体主题
		ConcreteSubject cs = new ConcreteSubject();

		ConcreteObserver co1 = new ConcreteObserver("观察者甲");
		ConcreteObserver co2 = new ConcreteObserver("观察者乙");
		ConcreteObserver co3 = new ConcreteObserver("观察者丙");

		// 注册观察者
		cs.attach(co1);
		cs.attach(co2);
		cs.attach(co3);

		System.out.println("具体主题状态改变为 3");
		System.out.println("******************");
		cs.setState(3);
		System.out.println("具体主题状态改变为 6");
		System.out.println("******************");
		cs.setState(6);
	}
}
运行客户端类控制台会输出以下结果:
具体主题状态改变为 3
******************
观察者: 观察者甲:--->3
观察者: 观察者乙:--->3
观察者: 观察者丙:--->3
具体主题状态改变为 6
******************
观察者: 观察者甲:--->6
观察者: 观察者乙:--->6
观察者: 观察者丙:--->6
使用观察者模式应该重点注意两个问题:
  1. 广播链的问题: 如果一个对象既是观察者也是被观察者,比如数据库中的触发器,A表插入数据后,B表会同时插入数据;B表插入数据后,C表会同时插入数据......这样数据库基本就毁掉了!建议在观察者模式中,最多出现一个对象同时作为观察者和被观察者(消息最多传递两次)。
  2. 异步处理问题:如果观察者很多,处理时间比较长,只能采用异步处理的方式,这是需要考虑线程安全以及队列的问题。

观察者模式的优缺点:
优点:
  1. 观察者模式在观察者和被观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者的聚集,每一个具体观察者都符合抽象观察者的接口。被观察者并不“认识”具体的观察者。
  2. 观察者模式支持广播通信,被观察者会向所有登记过的观察者发出通知。
缺点:
  1. 如果一个被观察者有很多直接或者间接的观察者,一一通知观察者会花费很多时间。
  2. 如果被观察者之间存在循环依赖,那么会出现循环调用,导致系统崩溃。
  3. 如果被观察者通知观察者是采用其他线程进行时,应该避免线程安全问题。
  4. 观察者虽然可以知道被观察者发生变化,但是不能知晓具体是怎么发生变化的。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值