观察者模式-常用设计模式
观察者模式-常用设计模式
dapengking 发表于4年前
观察者模式-常用设计模式
  • 发表于 4年前
  • 阅读 559
  • 收藏 7
  • 点赞 0
  • 评论 0

【腾讯云】如何购买服务器最划算?>>>   

摘要: 今天记录常用设计模式的第二篇-观察者模式。

观察者模式

    今天记录下,常用设计模式的第二篇-观察者模式。说起来,我知道观察者模式这个名词,在目前我所知道的设计模式中算是比较早的。因为,在之前闲的时候,曾经自学过android开发,在ui设计中的按钮事件,我印象中就是基于观察者模式实现的。你可以创建一个监听器类的对象,实现当按钮被点击时需要进行的动作。然后将这个对象(其实也就所谓的观察者)注册给按钮。这样,当有鼠标点击按钮时,按钮就会通知所有注册了的监听器类对象,调用其中的事件处理方法。

用headfirst设计模式一书中所说的一句话来概括就是:“当有趣的事情发生时,可千万别错过了!”。

    没错,观察者模式可以帮助对象了解运行现况。不会错过该对象感兴趣的事。而且,对象还可以在运行时决定是否需要继续接受通知。

    再引用一个书中的比方。如果了解报纸的订阅是怎么一回事的话,就会好理解的多。因为它们之间根本就是一样的道理,只是名字不太一样罢了。报纸的出版者就是观察者模式中的“主题(Subject)”,而报纸的订阅者其实也就是我们所谓的“观察者”。

严格的定义:观察者模式定义了对象之间一对多的依赖关系,这样一来,当一个对象改变状态的时候,它的所有依赖对象都可以收到通知并且自动更新状态。

观察者模式的UML类图(图片转自百度图片)

稍微解释下上图的意思:


  1. 首先,遵循面向接口而非面向实现编程的原则,我们需要两个接口:主题(Subject)和观察者(Observer)。在主题接口中声明了一般主题类中最基础的三个方法接口,分别为注册观察者(registerObserver)、删除观察者(removeObserver)和通知观察者(notifyObserver)。而观察者接口中通常至少会声明update方法接口,update将来的实现,用来在观察者收到主题的通知后,作出具体的动作;
  2. 接着,应该实现ConcreteSubject类,并实现Subject接口中的方法。通常情况下,在ConcreteSubject类中会维护一个Observer的容器,用来盛放注册进来的观察者对象的引用;
  3. 最后,当ConcreteSubject类的对象感知到状态改变后,会调用notifyOBserver()方法,在notifyOBserver()的实现中,我们会遍历ConcreteSubject类中Observer的容器中的所有Observer引用,对于每一个引用的对象,调用其update()方法。

通过上面三步的介绍,应该能够比较清楚的理解了观察者模式的基本原理了。在我自己的理解看来,观察者模式,其实与我的上篇帖子中的策略模式的最基本的实现机制相似:也是采用组合的方式,某些对象(这里是观察者对象)的引用组合到某个类(这里指主题类对象)的对象中。当某个事件发生时,主题类对象会采用一定的算法(这个算法不确定,最简单的方式是采用数组作为容器,然后采用遍历数组的方式。)遍历所有的观察者对象引用,并逐一调用update()方法。

与策略模式设计的初衷虽然不同(1.策略模式是为了封装经常变化的逻辑,将经常变动的代码,从比较稳定的代码中剥离出来,从而实现代码复用,并且可以实现在程序运行时的动态组合,提高了程序的灵活性。2.而这里的观察者模式则是为了实现消息的灵活订阅,这种一对多的关系)。但是它们之间在实现上的区别很小,都是通过组合的方式实现的。

一段简单的代码:


package observer;

public interface Subject {

	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
	public void notifyObserver();
	
}



package observer;

public interface Observer {
	public void update();
}



package observer;

import java.util.ArrayList;

public class ConcreteSubject implements Subject {

	private ArrayList<Observer> observers = new ArrayList<Observer>();
	
	@Override
	public void notifyObserver() {
		for (Observer observer : observers) {
			observer.update();
		}
	}

	@Override
	public void registerObserver(Observer o) {
		observers.add(o);
	}

	@Override
	public void removeObserver(Observer o) {
		observers.remove(o);
	}

}



package observer;

public class ConcreteObserver implements Observer {

	private String title = null;
	
	public ConcreteObserver(String title,Subject s) {
		this.title = title;
		s.registerObserver(this);
	}

	@Override
	public void update() {
		//观察者收到消息后的处理逻辑
		//
		//
		System.out.println(title + "收到了通知,并且相应了");
	}

}
//测试方法类
package observer;

public class Main {

	public static void main(String[] args) {
		Subject s = new ConcreteSubject();
		
		new ConcreteObserver("observer1",s);
		new ConcreteObserver("observer2",s);
		
		//模拟有事件发生时,调用notifyObserver()方法
		s.notifyObserver();
	}
}




运行结果:


--the end~




共有 人打赏支持
粉丝 7
博文 133
码字总数 53553
×
dapengking
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: