Java设计模式之观察者模式(Observer模式)介绍
观察者模式,也叫做发布订阅模式,是一种常用的设计模式。它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知并被自动更新。
观察者模式的结构
观察者模式由四个角色组成:抽象主题角色、具体主题角色、抽象观察者角色和具体观察者角色。
- 抽象主题角色:抽象主题角色定义了主题对象的基本操作,如增加、删除和通知观察者对象的方法。
- 具体主题角色:具体主题角色引用具体观察者对象,并实现抽象主题角色中的增加、删除和通知观察者的方法。通常具体主题角色是一个类,其中包含方法来设置和获取状态,并在状态改变时通知观察者对象。
- 抽象观察者角色:抽象观察者角色声明了更新的方法,当被通知时调用以更新自己。
- 具体观察者角色:具体观察者角色实现抽象观察者角色中定义的更新方法。通常具体观察者角色使用具体主题角色通知观察者对象状态的变化。
观察者模式的示例
下面我们通过两个示例来演示观察者模式的使用:
示例1:气象站
假设我们要开发一个气象站程序,该程序能够实时显示当前气温、湿度和气压。
需要考虑的问题是如何方便地扩展该程序——比如增加日志模块,将信息记录到文件中;增加短信提醒模块,将信息发送给用户等等。
这时候我们可以使用观察者模式。将气象站作为主题对象,将日志模块和用户模块作为观察者对象进行注册,当气象站数据发生更新时,会通知所有的观察者对象。
具体实现需要定义四个角色:
- 抽象主题角色:气象站主题,定义主题对象应该具有的操作。
- 具体主题角色:气象站,继承抽象主题角色,实现具体的操作方法。
- 抽象观察者角色:观察者,定义观察者对象应该具有的操作。
- 具体观察者角色:日志模块和用户模块,继承抽象观察者角色,实现更新方法。
示例代码如下:
// 抽象主题角色:气象站
interface WeatherStation {
void addObserver(Observer observer); // 增加观察者
void removeObserver(Observer observer); // 删除观察者
void notifyObservers(); // 通知观察者
}
// 具体主题角色:气象站
class ConcreteWeatherStation implements WeatherStation {
private List<Observer> observers; // 观察者列表
private float temperature; // 当前温度
private float humidity; // 当前湿度
private float pressure; // 当前气压
public ConcreteWeatherStation() {
observers = new ArrayList<>();
}
@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(temperature, humidity, pressure);
}
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
notifyObservers();
}
}
// 抽象观察者角色:观察者
interface Observer {
void update(float temperature, float humidity, float pressure); // 更新方法
}
// 具体观察者角色:日志模块
class LogModule implements Observer {
@Override
public void update(float temperature, float humidity, float pressure) {
// 将气象数据记录到日志文件中
System.out.println("Logging: temperature=" + temperature + ", humidity=" + humidity + ", pressure=" + pressure);
}
}
// 具体观察者角色:用户模块
class UserModule implements Observer {
@Override
public void update(float temperature, float humidity, float pressure) {
// 将气象数据发送给用户
System.out.println("User: temperature=" + temperature + ", humidity=" + humidity + ", pressure=" + pressure);
}
}
示例2:游戏角色属性
假设我们正在开发一款RPG游戏,游戏中有多种属性,如生命值、攻击力、防御力等。当游戏中角色的属性发生变化时,游戏内的各种界面需要及时更新这些变化。
这时候我们同样可以使用观察者模式。将游戏角色作为主题对象,将各种属性界面作为观察者对象进行注册,当角色属性发生更新时,会通知所有的观察者对象。
具体实现需要定义四个角色:
- 抽象主题角色:游戏角色,定义主题对象应该具有的操作。
- 具体主题角色:具体游戏角色,继承抽象主题角色,实现具体的操作方法。
- 抽象观察者角色:属性界面,定义观察者对象应该具有的操作。
- 具体观察者角色:生命值界面、攻击力界面和防御力界面,继承抽象观察者角色,实现更新方法。
示例代码如下:
// 抽象主题角色:游戏角色
interface GameCharacter {
void addObserver(Observer observer); // 增加观察者
void removeObserver(Observer observer); // 删除观察者
void notifyObservers(); // 通知观察者
}
// 具体主题角色:具体游戏角色
class ConcreteGameCharacter implements GameCharacter {
private List<Observer> observers; // 观察者列表
private int hp; // 当前生命值
private int attack; // 当前攻击力
private int defense; // 当前防御力
public ConcreteGameCharacter() {
observers = new ArrayList<>();
}
@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(hp, attack, defense);
}
}
public void setHp(int hp) {
this.hp = hp;
notifyObservers();
}
public void setAttack(int attack) {
this.attack = attack;
notifyObservers();
}
public void setDefense(int defense) {
this.defense = defense;
notifyObservers();
}
}
// 抽象观察者角色:属性界面
interface Observer {
void update(int hp, int attack, int defense); // 更新方法
}
// 具体观察者角色:生命值界面
class HpPanel implements Observer {
@Override
public void update(int hp, int attack, int defense) {
// 刷新生命值界面
System.out.println("HpPanel: hp=" + hp);
}
}
// 具体观察者角色:攻击力界面
class AttackPanel implements Observer {
@Override
public void update(int hp, int attack, int defense) {
// 刷新攻击力界面
System.out.println("AttackPanel: attack=" + attack);
}
}
// 具体观察者角色:防御力界面
class DefensePanel implements Observer {
@Override
public void update(int hp, int attack, int defense) {
// 刷新防御力界面
System.out.println("DefensePanel: defense=" + defense);
}
}
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java设计模式之观察者模式(Observer模式)介绍 - Python技术站