java 信号灯观察者模式_Java设计模式----观察者模式

本文介绍了观察者模式,它定义了一种一对多的依赖关系,使得多个观察者对象能同时监听某主题对象。通过示例展示了如何使用Java实现观察者模式,包括紧耦合和松耦合两种形式。文章最后讨论了在实际开发中为避免紧耦合而采用的消息中间件,以及在处理大量观察者时需要注意的内存管理问题。

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

交通信号灯相信大家都不陌生,红灯停、绿灯行,见了黄灯等一等。交通信号灯、海边的信号塔等等,都伫立在那里,随时准备给行人/货船发送信号,以提醒行人/货船该采取相应行动了。信号灯就是发布信号的对象,行人是接收信号并采取具体行动的观察者。这一过程,在程序设计中也常常用到,即本文介绍的观察者模式。

1.观察者模式

观察者模式(Observer Pattern)定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

在事件驱动的GUI开发中观察者模式十分常用。另外,著名的MVC软件设计思想也应用了观察者模式:

Model 业务模型,相当于观察者模式中的主题对象

View 视图层,相当于观察者

Controller 控制器,协调M和V

当Model数据发生变化时,会通知View更新视图。所以,观察者模式又叫做模型-视图模式,或者发布-订阅模式。

2. 代码实现

2.1 紧耦合形式

Observer抽象类,有三个子类:HexObserver十六进制, OctObserver八进制,BinObserver二进制,注意观察着Observer持有主题Subject的引用。

Subject主题对象持有Observer的引用,并提供添加add观察者的方法, 当Subject状态改变时setState, 会调用execute方法,execute方法中遍历所有观察者对象并调用每个观察者对象的update方法更新,观察者对象的update方法中,通过回调主题对象的getState()方法获取主题的状态。

这种方式Subject持有Observer引用, Observer也持有Subject的引用,就是紧耦合的实现方式。

abstract classObserver {protectedSubject subject;public abstract voidupdate();

}classSubject {private List observers = new ArrayList<>();private intstate;public voidadd(Observer o) {

observers.add(o);

}public intgetState() {returnstate;

}public void setState(intvalue) {this.state =value;

execute();

}private voidexecute() {for(Observer observer : observers) {

observer.update();

}

}

}class HexObserver extendsObserver {publicHexObserver(Subject subject) {this.subject =subject;this.subject.add(this);

}public voidupdate() {

System.out.print(" " +Integer.toHexString(subject.getState()));

}

}class OctObserver extendsObserver {publicOctObserver(Subject subject) {this.subject =subject;this.subject.add( this);

}public voidupdate() {

System.out.print(" " +Integer.toOctalString(subject.getState()));

}

}class BinObserver extendsObserver {publicBinObserver(Subject subject) {this.subject =subject;this.subject.add(this);

}public voidupdate() {

System.out.print(" " +Integer.toBinaryString(subject.getState()));

}

}public classObserverDemo {public static voidmain( String[] args ) {

Subject sub= newSubject();//Client configures the number and type of Observers

newHexObserver(sub);newOctObserver(sub);newBinObserver(sub);

Scanner scan= newScanner(System.in);for (int i = 0; i < 5; i++) {

System.out.print("\nEnter a number: ");

sub.setState(scan.nextInt());

}

}

}

2.2 松耦合形式

以下代码基于jdk1.8以上,定义内部类,可以避免在Observer中定义Subject的引用。

EventSource事件源, scanSystemIn()方法监听控制台输入,当控制台有字符串输入时,EventSource会通知Observer进行update操作。

/*** 事件源*/

classEventSource {public interfaceObserver {voidupdate(String event);

}private final List observers = new ArrayList<>();public voidaddObserver(Observer observer) {

observers.add(observer);

}public voidscanSystemIn() {

Scanner scanner= newScanner(System.in);while(scanner.hasNextLine()) {

String line=scanner.nextLine();

notifyObservers(line);

}

}private voidnotifyObservers(String event) {

observers.forEach(observer->observer.update(event));

}

}

调用

public classObserverDemo {public static voidmain(String[] args) {

EventSource eventSource= newEventSource();for (int i = 0; i < 3; i++) {

eventSource.addObserver(event->{

System.out.println("Received response: " +event);

});

}

eventSource.scanSystemIn();

}

}

控制台输入"click",然后事件源监听到,通知Observer,Observer将消息打印出来:

click

Received response: click

Received response: click

Received response: click

3.总结

其实为了避免紧耦合,实际开发中往往在Subject和Observer之间加一个中间对象,这个中间对像本质上就是一个队列,当Subject状态发生变化时,这个变化信息传到中间对象队列中,由中间对象对这条消息进行处理,包装成Observer统一的一种接收形式,然后根据某种策略发给Observer。消息中间件就是这样一种实现,

另外,注意主题对象由于持有观察着对象集合,如果观察者数量庞大时,要注意内存的占用,避免发生内存泄漏,通常,可以考虑弱引用weak reference来避免内存占用过高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值