设计模式(16):观察者模式

核心

  • 观察者模式主要用于1:N的通知。当一个对象(目标对象Subject或者Abservable)的状态变化时,他需要及时告知一系列对象(观察者对象,Observer),令 他们做出响应。
  • 通知观察者的方式:
    • 推:
      • 每次都会把通知以广播方式发送给所有观察者,所有观察者只能被动接收。
    • 拉:
      • 观察者只要知道有情况变化即可。至于什么时候获取内容,获取什么内容,都可以自主决定。

观察者模式角色

  • 抽象主题对象(Subject): 聚合所有的观察者,提供注册和移除观察者的方法,并且提供通知所有观察者的方法。
  • 具体的主题对象(ConcreteSubject): 实现抽象主题对象。并提供状态修改方法;
  • 抽象观察者(Observer): 提供更新观察者的方法;
  • 具体观察者(ConcreteObserver): 实现抽象观察者.

场景

  • 聊天室程序的创建。服务器创建好后,A,B,C三个客户端连上来公开聊天。A向服务器发送数据,服务器端聊天数据改变。我们希望将这些聊天数据分别发给其他在线的客户。也就是说,每个客户端需要更新服务端的数据;
  • 网站上,很多人订阅了"java主题"的新闻,当有这个主题新闻时,就会将这些新闻发送给所有订阅的人。
    这些场景,我们都可以使用观察者模式来处理。我们可以把多个订阅者、客户端称之为观察者;需要同步给多个订阅者的数据封装到对象中,称之为目标。

开发中常见的场景

  • 聊天室程序的服务器转发给所有客户端;
  • 网络游戏场景中,服务器将客户端的状态进行分发;
  • 邮件订阅;
  • servlet中监听器的实现;
  • spring项目中的事件监听器的实现;

代码实现

  • 抽象主题对象
java 复制代码
/**
 * 抽象主题对象
 */
public abstract class Subject {
	// 所有的观察者
	protected List<Observer> list = new ArrayList<Observer>();	
	public void registerObserver(Observer obs){
		list.add(obs);
	}
	public void removeObserver(Observer obs){
		list.remove(obs);
	}
	//通知所有观察者更新状态
	public void notifyAllObserver(){
		for(Observer obs:list){
			obs.update(this);
		}
	}
}
  • 具体主题对象
java 复制代码
/**
 * 具体的主题对象
 */
public class ConcreteSubject extends Subject{
	private int state;
	public int getState() {
		return state;
	}
	public void setState(int state) {
		this.state = state;
		//主题(目标)对象发生变化,请通知所有观察者
		this.notifyAllObserver();
	}
}
  • 抽象观察者类
java 复制代码
/**
 * 	抽象观察者
 */
public interface Observer {
	void update(Subject subject);	
}
  • 具体观察者类
java 复制代码
/**
 * 具体观察者A
 */
public class AObserver implements Observer{
	private int state;
	public int getState() {
		return state;
	}
	public void setState(int state) {
		this.state = state;
	}
	@Override
	public void update(Subject subject) {
		this.state=((ConcreteSubject)subject).getState();
	}
}
/**
 * 具体观察者B
 */
public class BObserver implements Observer{
	private int state;
	
	public int getState() {
		return state;
	}
	public void setState(int state) {
		this.state = state;
	}
	@Override
	public void update(Subject subject) {
		this.state=((ConcreteSubject)subject).getState();
	}
}
  • 客户端调用
java 复制代码
public static void main(String[] args) {
	//目标对象
	ConcreteSubject subject=new ConcreteSubject();
	//创建多个观察者
	AObserver observerA=new AObserver();
	BObserver observerB=new BObserver();
	//将观察者添加到subject对象的观察者队伍中
	subject.registerObserver(observerA);
	subject.registerObserver(observerB);
	
	//改变subject状态之前
	System.out.println("改变subject状态之前");
	System.out.println(observerA.getState());
	System.out.println(observerB.getState());
	
	//改变subject状态
	subject.setState(300);
	//观察者状态是否发生变换
	System.out.println("改变subject状态之后");
	System.out.println(observerA.getState());
	System.out.println(observerB.getState());
}

更多设计模式学习:

设计模式(1):介绍

设计模式(2):单例模式

设计模式(3):工厂模式

设计模式(4):建造者模式

设计模式(5):原型模式

设计模式(6):桥接模式

设计模式(7):装饰器模式

设计模式(8):组合模式

设计模式(9):外观模式

设计模式(10):享元模式

设计模式(11):适配器模式

设计模式(12):代理模式

设计模式(13):模板方法模式

设计模式(14):命令模式

设计模式(15):迭代器模式

设计模式持续更新中...

相关推荐
向宇it10 分钟前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
小蜗牛慢慢爬行12 分钟前
Hibernate、JPA、Spring DATA JPA、Hibernate 代理和架构
java·架构·hibernate
星河梦瑾1 小时前
SpringBoot相关漏洞学习资料
java·经验分享·spring boot·安全
黄名富1 小时前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
love静思冥想1 小时前
JMeter 使用详解
java·jmeter
言、雲1 小时前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库
TT哇1 小时前
【数据结构练习题】链表与LinkedList
java·数据结构·链表
东风吹柳2 小时前
观察者模式(sigslot in C++)
c++·观察者模式·信号槽·sigslot
Yvemil72 小时前
《开启微服务之旅:Spring Boot 从入门到实践》(三)
java
Anna。。2 小时前
Java入门2-idea 第五章:IO流(java.io包中)
java·开发语言·intellij-idea