观察者模式

本文深入解析观察者模式的定义及应用场景,通过自定义实现和JDK内置类展示如何在Java中应用观察者模式,实现对象间依赖的通知机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

观察者模式

定义:一个对象(subject)被其他多个对象(observer)所依赖。则当一个对象变化时,发出通知,其它依赖该对象的对象都会收到通知,并且随着变化。 

使用场景1:声音报警器和闪光灯报警器分别订阅热水器温度,热水器温度过高时,发出通知,两个报警器分别发声、闪光以实现报警。 
使用场景2:多人订阅微信公众号,该公众号有更新文章时,自动通知每个订阅的用户。

1. 自定义观察者模式实现

定义Subject接口

public interface Subject {

	// 增加观察者
	public void addObserver(Observer o);
	// 删除观察者
	public void removeObserver(Observer o);
	// 通知所有观察者
	public void notifyAllObserver();
	// 发生的一些改变
	public void changed();
}

被观察对象(实现Subject接口)

import java.util.ArrayList;

public class MySubject implements Subject {

	// 保存观察者的数据结构
	private ArrayList<Observer> list = new ArrayList<Observer>();
	
	@Override
	public void addObserver(Observer o) {
		list.add(o);
	}

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

	@Override
	public void notifyAllObserver() {
		for (Observer observer : list) {
			observer.update();
		}
	}

	@Override
	public void changed() {
		// 观察的对象MySubject发生变化,通知所有的观察者
		System.out.println("MySubject发生变化。。。");
		notifyAllObserver();
	}

}

定义观察者接口

public interface Observer {

	public void update();
}

定义两个观察者(实现Observer接口)

public class Observer1 implements Observer {

	@Override
	public void update() {
		System.out.println("观察者1,收到信息,做出相应的改变。。。");
	}

}
public class Observer2 implements Observer {

	@Override
	public void update() {
		System.out.println("观察者2,收到信息,做出相应的改变。。。");
	}

}

测试

public class ObserverPatternTest {

	public static void main(String[] args) {
		Subject sub = new MySubject();
		Observer o1 = new Observer1();
		Observer o2 = new Observer2();
		// 注册或订阅这两个对象
		// 注册顺序决定通知顺序,最先注册的最先通知,类似于队列,与jdk内置的观察者刚好相反
		sub.addObserver(o1);
		sub.addObserver(o2);
		// 被观察的对象sub发生改变,通知所有的观察者
		sub.changed();
		// 移除某个观察者
		sub.removeObserver(o1);
		// 再次通知所有观察者
		sub.changed();
	}
}

运行结果(注意通知观察者的先后顺序)

2.使用JDK内置类、接口实现观察者模式

定义被观察者对象(继承Observable类

import java.util.Observable;

public class JdkSubject extends Observable {

	private int property1;
	private int property2;

	// 定义内部类,用于传送数据
	class Data {
		private int property1;
		private int property2;

		public Data() {
		}

		public Data(int property1, int property2) {
			this.property1 = property1;
			this.property2 = property2;
		}

		public int getProperty1() {
			return property1;
		}

		public int getProperty2() {
			return property2;
		}

	}

	// 设置数据
	public void setData(int proprety1, int property2) {
		this.property1 = proprety1;
		this.property2 = property2;
		// 有数据变化,通知所有的观察者
		changed();
	}

	public void changed() {
		// 表示数据是由更新的,数据变化了,必须调用此方法,才能去通知观察者
		setChanged();
		// 通知观察者时,把信息传给观察者
		notifyObservers(new Data(getProperty1(), getProperty2()));
	}

	public int getProperty1() {
		return property1;
	}

	public void setProperty1(int property1) {
		this.property1 = property1;
	}

	public int getProperty2() {
		return property2;
	}

	public void setProperty2(int property2) {
		this.property2 = property2;
	}

}

定义两个观察者(实现Observer接口(JDK内置接口))

import java.util.Observable;
import java.util.Observer;

import design_pattern.observer_pattern.jdkImplement.JdkSubject.Data;

public class JdkObserver1 implements Observer {

	// 要改变的两个属性
	private int property1;
	private int property2;

	@Override
	public void update(Observable o, Object arg) {
		this.property1 = ((Data) (arg)).getProperty1();
		this.property2 = ((Data) (arg)).getProperty2();
		display();
	}

	public void display() {
		System.out.println("观察者1,收到消息,并改变数据");
		System.out.println("观察者1--property1:  " + property1);
		System.out.println("观察者1--property2:  " + property2);
	}

}
import java.util.Observable;
import java.util.Observer;

import design_pattern.observer_pattern.jdkImplement.JdkSubject.Data;

public class JdkObserver2 implements Observer {
	
	// 要改变的两个属性
	private int property1;
	private int property2;

	@Override
	public void update(Observable o, Object arg) {
		this.property1 = ((Data) (arg)).getProperty1();
		this.property2 = ((Data) (arg)).getProperty2();
		display();
	}
	
	public void display() {
		System.out.println("观察者2,收到消息,并改变数据");
		System.out.println("观察者2--property1:  " + property1);
		System.out.println("观察者2--property2:  " + property2);
	}

}

测试

import java.util.Observer;

public class JdkObserverPatternTest {

	public static void main(String[] args) {
		// 被观察的对象
		JdkSubject sub = new JdkSubject();
		// 两个观察者
		Observer o1 = new JdkObserver1();
		Observer o2 = new JdkObserver2();
		// 注册或订阅两个观察者
		// 注册顺序决定通知顺序,jdk中内置的观察者是:最先注册的最晚通知,类似于栈
		sub.addObserver(o1);
		sub.addObserver(o2);
		// 被观察对象发生改变,通知观察者做出改变
		sub.setData(11, 22);
		
		// 移除一个观察者,再去通知
		sub.deleteObserver(o1);
		sub.setData(33, 44);
	}
}

运行结果(注意通知观察者的先后顺序)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值