观察者模式(Observer Pattern)是一种行为型设计模式,用于在对象之间建立一对多的依赖关系,当一个对象的状态发生变化时,其相关依赖对象会自动收到通知并进行相应处理。
主题和观察者都实现相应接口,在主题中维护一个观察者列表,并在状态改变时遍历通知所有观察者。
实现原理:
实现代码:
import java.util.ArrayList;
import java.util.List;
// 观察者接口
interface Observer {
void update(String newState);
}
// 主题接口
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 具体主题类
class ConcreteSubject implements Subject {
private List observers = new ArrayList<>();
private String state;
public void setState(String newState) {
this.state = newState;
notifyObservers();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
}
// 具体观察者类
class ConcreteObserver implements Observer {
private String observerState;
@Override
public void update(String newState) {
this.observerState = newState;
// 执行相应操作
System.out.println("Observer state updated: " + observerState);
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer observer1 = new ConcreteObserver();
Observer observer2 = new ConcreteObserver();
subject.registerObserver(observer1);
subject.registerObserver(observer2);
subject.setState("New State");
}
}
上述代码中,我们定义了一个观察者接口 Observer,其中包括了一个更新方法 update。然后,我们定义了一个主题接口 Subject,其中包括注册观察者、移除观察者和通知观察者等方法。接着,我们创建了具体的主题类 ConcreteSubject,该类维护了一个观察者列表,并在状态改变时遍历通知所有注册的观察者。最后,我们创建了具体的观察者类 ConcreteObserver 实现更新方法,在收到主题通知时执行相应操作。
使用自定义接口实现方式的问题:
尽管存在以上问题,使用自定义接口实现方式是观察者模式的经典实现方式,并且具有简单、直观的特点。
主题继承Observable类并调用其方法进行状态改变通知,观察者实现Observer接口并注册到主题上。
实现原理:
实现代码:
import java.util.Observable;
import java.util.Observer;
// 具体主题类
class ConcreteSubject extends Observable {
private String state;
public void setState(String newState) {
this.state = newState;
setChanged();
notifyObservers(state);
}
}
// 具体观察者类
class ConcreteObserver implements Observer {
private String observerState;
@Override
public void update(Observable o, Object arg) {
if (o instanceof ConcreteSubject) {
this.observerState = (String) arg;
// 执行相应操作
System.out.println("Observer state updated: " + observerState);
}
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer observer1 = new ConcreteObserver();
Observer observer2 = new ConcreteObserver();
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.setState("New State");
}
}
上述代码中,我们创建了一个具体主题类 ConcreteSubject,该类继承自Java内置的Observable类。在该类中,我们定义了状态改变方法 setState(),并在该方法中调用setChanged()和notifyObservers()来通知所有注册的观察者。
然后,我们创建了一个具体观察者类 ConcreteObserver 实现Observer接口,并在update()方法中定义观察者收到通知后的操作。
最后,在使用示例中,我们创建了一个具体主题对象和两个具体观察者对象,并将观察者注册到主题上。当主题状态改变时,会自动通知所有注册的观察者进行相应操作。使用Java内置Observable和Observer实现方式存在以下问题:
尽管存在以上问题,使用Java内置Observable和Observer实现方式可以更方便地利用已有工具来快速实现观察者模式。
通过定义事件类、监听器接口以及注册监听器等方式来实现观察者模式。当事件发生时,主题发布该事件给已注册的监听器。
实现原理:
实现代码:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// 事件类
class Event {
private String eventType;
private Map eventData = new HashMap<>();
public Event(String eventType) {
this.eventType = eventType;
}
public String getEventType() {
return eventType;
}
public void addData(String key, Object value) {
eventData.put(key, value);
}
public Object getData(String key) {
return eventData.get(key);
}
}
// 主题接口
interface Subject {
void registerObserver(Observer observer, String eventType);
void removeObserver(Observer observer, String eventType);
void notifyObservers(Event event);
}
// 具体主题类
class ConcreteSubject implements Subject {
private Map> observersMap = new HashMap<>();
@Override
public void registerObserver(Observer observer, String eventType) {
List observers = observersMap.getOrDefault(eventType, new ArrayList<>());
observers.add(observer);
observersMap.put(eventType, observers);
}
@Override
public void removeObserver(Observer observer, String eventType) {
if (observersMap.containsKey(eventType)) {
List observes = observersMap.get(eventType);
observes.remove(observer);
if (observes.isEmpty()) { // 若没有观察者监听该事件,则从观察者列表中移除该事件类型
observersMap.remove(eventType);
}
}
}
@Override
public void notifyObservers(Event event) {
if (event != null && event.getEventType() != null &&
observersMap.containsKey(event.getEventType())) {
for (Observer observe : observersMap.get(event.getEventType())) {
observe.onEventReceived(event);
}
}
}
}
// 观察者接口
interface Observer {
void onEventReceived(Event event);
}
// 具体观察者类1,处理特定类型事件的处理器之一
class ConcreteHandler1 implements Observer {
@Override
public void onEventReceived(Event event) {
if ("eventType1".equals(event.getEventType())) {
// 执行相应操作
System.out.println("ConcreteHandler1 received Event: " + event.getData("data"));
}
}
}
// 具体观察者类2,处理特定类型事件的处理器之一
class ConcreteHandler2 implements Observer {
@Override
public void onEventReceived(Event event) {
if ("eventType2".equals(event.getEventType())) {
// 执行相应操作
System.out.println("ConcreteHandler2 received Event: " + event.getData("data"));
}
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer handler1 = new ConcreteHandler1();
Observer handler2 = new ConcreteHandler2();
subject.registerObserver(handler1, "eventType1");
subject.registerObserver(handler2, "eventType2");
Event event1 = new Event("eventType1");
event1.addData("data", "Event data for eventType1");
Event event2 = new Event("eventType2");
event2.addData("data", "Event data for eventType2");
subject.notifyObservers(event1);
subject.notifyObservers(event2);
}
}
上述代码中,我们定义了一个事件类 Event
,其中包含了需要传递给观察者的数据。然后,我们创建了主题接口 Subject
和具体主题类 ConcreteSubject
来实现注册观察者、移除观察者和通知观察者等方法。
接着,我们定义了一个观察者接口 Observer
,并创建两个具体的处理器类(例如:ConcreteHandler1
和 `ConcreteHandler12)来实现对不同类型事件的监听和相应操作。
在使用示例中,我们创建了一个具体主题对象和两个具体观察者对象,并将观察者注册到主题上。当主题触发特定类型事件时,会自动通知对应的处理器进行相应操作。
使用事件机制实现方式可以更加灵活地处理不同类型的事件,并使得代码结构更清晰。