设计模式之观察者模式(发布订阅模式)

说明:本文参照《大话设计模式》中的案例做简要解析

观察者模式:

        又叫发布-订阅模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在发生变化时,会通知所有观察者对象,使他们能够更新自己。

        我自己的理解,可以拿咱们都比较熟悉的上课来做比喻,在一个教室里,老师就是通知者,所有正在上课的学生就是观察者,老师说下课,所有的学生下课回家。老师说的“下课”,就是这里的“主题”,也可以叫话题(Topic),学生接受到这个“主题”,采取相应的动作-(收拾东西回家)。

类图及简要说明:


Subject类,可理解为主题或者抽象通知者,一般用抽象类或接口实现。它把所有的观察者对象的引用保存在一个集合里,每个主题都可以有任何数量的观察者。

package com.uu.designPattern.observer;

import java.util.ArrayList;
import java.util.List;

/**
  ***********************************************
  * 主题或抽象通知者
  * 	一般用一个抽象类或一个接口实现,把所有对观察者的引用保存在一个集合里,每一个主题都可以有任何数量的观察者。
  * 	抽象主题提供一个接口,可以增加和删除观察者。
  * @author UU
  * @date 2018年7月5日 下午3:00:23
  * @version 1.0
  ***********************************************
 */
public abstract class Subject {

	List<Observer> observers = new ArrayList<>();
	
	/**添加观察者*/
	public abstract void attach(Observer observer); 
	/**移除观察者*/
	public abstract void detach(Observer observer);
	
	/**
	 * 通知观察者
	 */
	public void notifyAllObserver() {
		observers.forEach(Observer::update);
	}
	
}

Observer,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时,更新自己。这个接口称为更新接口,更新接口一般都有一个update方法。

package com.uu.designPattern.observer;

/**
  ***********************************************
  * 观察者
  * @author UU
  * @date 2018年7月5日 下午3:02:34
  * @version 1.0
  ***********************************************
 */
public abstract class Observer {

	public abstract void update();
}

ConcreteSubject,具体的主题或具体的通知者,将有关状态存入具体观察者对象;在具体主题的内部状态发生改变时,给所有已经注册的观察者发出通知。其实这里的意思主要是触发通知者发出通知,然后观察者根据通知信息作出相应的动作。

package com.uu.designPattern.observer;

/**
 ***********************************************
 * 具体的主题或通知者,将有关状态存入具体主题对象,在具体的主题对象的内部状态发生改变时,通知所有已经注册的观察者
 * @author UU
 * @date 2018年7月5日 下午3:42:40
 * @version 1.0
 ***********************************************
 */
public class ConcreteSubject extends Subject{

	private String state;

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

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

	@Override
	public void detach(Observer observer) {
		this.observers.remove(observer);
	}

}

ConcreteObserver,具体的观察者,实现抽象观察者所要实现的更新方法,以便使自身的状态与主题的状态保持一致。具体观察者包含一个具体主题对象的引用。

package com.uu.designPattern.observer;

/**
 ***********************************************
 * 具体的观察者
 * 
 * @author UU
 * @date 2018年7月5日 下午3:46:47
 * @version 1.0
 ***********************************************
 */
public class ConcreteObserver extends Observer {

	private String name;
	private String state;
	private ConcreteSubject subject;

	public ConcreteObserver(String name, ConcreteSubject subject) {
		super();
		this.name = name;
		this.subject = subject;
	}

	@Override
	public void update() {
		state = subject.getState();
		System.out.println("观察者" + this.name + "的新状态是:" + state);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	public ConcreteSubject getSubject() {
		return subject;
	}

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

}

测试类:

package com.uu.designPattern.observer;

public class ObserverTest {

	public static void main(String[] args) {
		
		ConcreteSubject subject = new ConcreteSubject();
		subject.attach(new ConcreteObserver("AA", subject));
		subject.attach(new ConcreteObserver("BB", subject));
		
		subject.setState("ABC");
		subject.notifyAllObserver();
		
		subject.setState("CCC");
		subject.notifyAllObserver();
		
	}
}

运行结果:

观察者AA的新状态是:ABC
观察者BB的新状态是:ABC
观察者AA的新状态是:CCC
观察者BB的新状态是:CCC

观察者模式的特点:

        主要是为了解决各类直接的耦合度,一个出题可以有任意数量的观察者,一旦主题发生改变,所有注册的观察者都可以得到通知。主题发出通知时,并不需要知道他的观察者都是哪些,也就是说,具体的观察者是谁,他根本不需要知道,而任何一个观察者不知道也不需要知道其他观察者的存在。

        再拿老师和学生来讲,老师不需要知道每个学生都是谁(也许是刚来的新老师),老师只需要发出下课的指令就可以了,然后这个指令会被所有正在上课的学生接受到。对于每个学生个体而言,也不需要知道是否有其他学生是否存在,只要接受到老师的指令,照做就OK了。

观察者模式的应用场景:

        当一个对象的改变需要同时改变其他对象时,并且它不知道具体有多少对象需要改变。

总的来讲,观察者模式所做的工作就是解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。

在Dubbo的注册中心Zookeeper中的服务注册和订阅应用的就是这种模式。


以上全是个人见解,若有错误,还望指正。

猜你喜欢

转载自blog.csdn.net/qq_33561055/article/details/80928599