16.观察者模式

定义

观察者模式(Observer Pattern)也叫做发布订阅模式(Publish/subscrible)
定义:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态时,则所有依赖于他的对象都会得到通知并被自动更新

Subject被观察者:定义被观察者必须实现的职责,必须能够动态的增加/取消观察者
Observer观察者:观察者接收到消息后,即进行update操作,对接收到的信息进行处理
ConcreteSubject具体被观察者:定义被观察者的业务逻辑
ConcreteObserver具体观察者:定义每个观察者接收到消息的业务逻辑

通用源码

//被观察者
//用Vector或是ArrayList都可以,视情况而定
public abstract class Subject{
	//定义一个观察者数组
	private Vector<Observer> obsVector = new Vector<Observer>();
	//增加一个观察者
	public void addObserver(Observer o){
		this.obsVector.add(o);
	}
	//删除一个观察者
	public void delObserver(Observer o){
		this.obsVector.remove(o);
	}
	//通知所有观察者
	public void notifyObservers(){
		for(Observer o:this.obsVector){
			o.update();
		}
	}
}

//具体被观察类
public class ConcreteSubject extends Subject{
	//具体业务
	public void doSomething(){
		super.notifyObservers();
	}
}

//观察者类
public interface Observer{
	//更新方法
	public void update();
}

/具体被观察者类
public class ConcreteObserver implements Observer{
	//实现更新方法
	public void update(){
		System.out.println("接收到消息,进行处理");
	}
}

//场景类
public class Client{
	public static void main(String[] args){
		//创建一个被观察者
		ConcreteSubject subject = new ConcreteSubject();
		//定义一个观察者
		ConcreteObserver obs = new ConcreteObserver();
		//观察者观察被观察者
		subject.addObserver(obs);
		//观察者开始活动
		subject.doSomething();
	}
}

应用

优点

  1. 观察者和被观察者之间是抽象耦合:易于扩展
  2. 可用于建立一套触发机制

缺点

观察者模式需要考虑到开发效率以及运行效率,一个被观察者多个观察者就会导致系统复杂,且在java中消息的通知默认是顺序执行,一个卡住后,会影响整体

使用场景

  1. 关联行为场景
  2. 事件多级触发场景
  3. 跨系统的消息交换场景

注意事项

  1. 广播链问题:如果有多个角色既是观察者又是被观察者,逻辑就会很复杂,维护很麻烦,所以一般情况下,一个观察者模式中最多出现一个对象既是观察者又是被观察者,即–消息最多转发一次
  2. 异步处理问题

扩展

java在一开始就提供了一个可扩展的父类——java.util.Observable实现类和java.util.Observer接口,我们直接实现即可

现实实践

现实中例如:文件系统(文件/磁盘管理器)/广播收音机(电台/收音机),都是很明显的例子

### 观察者模式的定义 观察者模式(Observer Pattern)是一种行为型设计模式,它定义了对象之间的一种一对多的依赖关系,使得每当一个对象改变状态时,其所有依赖者都会收到通知并自动更新。这种模式通常用于实现分布式事件处理系统,其中一个对象的行为依赖于另一个对象的状态 [^1]。 在观察者模式中,被观察者(Subject)维护一组观察者(Observer),并通过调用观察者的回调方法来通知它们状态的变化。这种机制允许对象之间保持松散耦合,因为被观察者不需要知道具体的观察者是谁,只需要知道它们都符合一个共同的接口 [^3]。 --- ### 观察者模式的核心角色 - **Subject(被观察者)**:维护一组观察者,并提供添加、删除和通知观察者的方法。 - **Observer(观察者)**:定义一个或多个回调方法,用于接收被观察者的通知。 - **ConcreteSubject(具体被观察者)**:当其状态发生变化时,会通知所有注册的观察者。 - **ConcreteObserver(具体观察者)**:实现观察者的回调方法,以响应被观察者的通知。 --- ### 观察者模式的优点 - **解耦**:观察者模式允许被观察者和观察者之间建立一种抽象的耦合关系,而不是紧密的依赖关系。这意味着被观察者不需要知道具体的观察者是谁,只需要知道它们都符合一个共同的接口 [^3]。 - **灵活性**:基于接口的设计使得观察者模式具有很高的灵活性。可以灵活地添加新的观察者或改变观察者的行为,而不需要修改被观察者的代码 [^3]。 - **维护一致性**:通过建立松散的依赖关系,观察者模式有助于维护系统的一致性。当被观察者的状态发生变化时,所有依赖于此状态的观察者都会得到通知并进行更新,从而保持系统的一致性 [^3]。 --- ### 观察者模式的缺点 - **过多的通知**:当被观察者对象有很多直接和间接的观察者时,每次状态变化都需要通知所有观察者,这可能会花费很多时间,尤其是在有大量观察者的情况下,可能会影响程序的执行效率 [^3]。 - **循环依赖问题**:如果观察者和被观察者之间存在循环依赖,可能会导致系统崩溃。在使用观察者模式时,需要特别注意这一点,以避免出现循环调用的情况 [^3]。 - **开发调试复杂**:应用观察者模式时,需要考虑开发小路问题,包括被观察者和多个观察者的管理和调试,这可能会增加开发的复杂性 。 - **没有提供变化细节**:观察者模式只能让观察者知道被观察对象的变化,但不能提供关于变化的具体细节,这意味着观察者只能知道发生了变化,但不知道是如何变化的 [^3]。 --- ### 使用示例(Java 实现) 以下是一个简单的 Java 示例,展示如何实现观察者模式: #### 被观察者接口 ```java /** * 被观察者接口 */ public interface Subject { void addObserver(Observer observer); void removeObserver(Observer observer); void notifyObservers(); } ``` #### 具体被观察者类 ```java import java.util.ArrayList; import java.util.List; /** * 具体被观察者类 */ public class ConcreteSubject implements Subject { private List<Observer> observers = new ArrayList<>(); private String state; public void setState(String state) { this.state = state; notifyObservers(); } public String getState() { return state; } @Override public void addObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { observers.remove(observer); } @Override public void notifyObservers() { for (Observer observer : observers) { observer.update(this); } } } ``` #### 观察者接口 ```java /** * 观察者接口 */ public interface Observer { void update(Subject subject); } ``` #### 具体观察者类 ```java /** * 具体观察者类 */ public class ConcreteObserver implements Observer { private String name; public ConcreteObserver(String name) { this.name = name; } @Override public void update(Subject subject) { if (subject instanceof ConcreteSubject) { System.out.println(name + " 收到通知,当前状态为:" + ((ConcreteSubject) subject).getState()); } } } ``` #### 测试类 ```java public class Main { public static void main(String[] args) { ConcreteSubject subject = new ConcreteSubject(); Observer observer1 = new ConcreteObserver("观察者1"); Observer observer2 = new ConcreteObserver("观察者2"); subject.addObserver(observer1); subject.addObserver(observer2); subject.setState("新状态"); } } ``` 运行结果: ``` 观察者1 收到通知,当前状态为:新状态 观察者2 收到通知,当前状态为:新状态 ``` --- ### 相关问题 1. 如何在实际项目中选择使用观察者模式? 2. 观察者模式与其他行为型设计模式有何异同? 3. 在多线程环境下如何安全地使用观察者模式? 4. 观察者模式是否适用于大规模系统的事件通知机制?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值