观察者模式在java中的应用_Java设计模式之观察者模式及在Android中的应用 | KaelLi的博客...

观察者模式简介

Observer Pattern,观察者模式,也是设计模式中非常常见的一种,在此模式下,一个对象(被观察者)可以管理一大批观察者对象,并且在自己的状态发生变化时,通过接口通知观察者们,而观察者们接到通知后,可以分别作出相应的动作。

观察者与被观察者之间不会产生直接耦合,但它们是抽象耦合的(通过接口),这算是一个优点,但毕竟还是存在耦合。

观察者模式解读

13478a8f8484e7b983dbbeadc6032b63.gif

从网上找来一张观察者模式的简单类图,从这张图里,我们对观察者模式中的各个角色进行解读。

Subject(被观察者)

是一个接口(实际上也有人使用抽象类),主要包含了3个方法:

addObserver方法可以添加观察者对象,可以理解为观察者把自己注册到了被观察者这里,只有注册了的观察者,才能接到被观察者的通知。

deleteObserver方法是将观察者移除,被移除的观察者自然就不能再接到通知了。

notifyObserves方法可以把通知发送给所有的已注册的观察者,至于观察者们后续做什么事情,被观察者是完全不关心的。

Observer(观察者)

也是一个接口,必须实现的只有一个notify方法(当然在Java里你得把notify改成其他名字),被观察者通过调用这个方法,让观察者了解到事件的发生。

ConcreteSubject(被观察者的具体实现)

在这里可以写被观察者的具体业务逻辑,另外还需要一个存储观察者的集合。一般情况下使用ArrayList就行,当然如果考虑到多线程场景,可以使用CopyOnWriteArraySet,因为线程安全嘛。

ConcreteObserver(观察者的具体实现)

在这里写的是观察者的具体业务逻辑。毕竟一个观察者如果除了接收消息没有别的能力,那么这个观察者就没有意义了。观察者模式嘛,观察者从被观察者那里接收到了消息之后的逻辑才更加重要。

实现观察者模式的Java代码

先定义观察者接口:

// 这里的接口很简单,就只有一个update方法,被观察者通过此方法通知观察者。

public interface Observer {

void update(String message);

}

1

2

3

4

// 这里的接口很简单,就只有一个update方法,被观察者通过此方法通知观察者。

publicinterfaceObserver{

voidupdate(Stringmessage);

}

然后是观察者接口:

public interface Subject {

// 注册观察者

void addObserver(Observer observer);

// 删除观察者

void deleteObserver(Observer observer);

// 通知观察者

void notifyObservers();

}

1

2

3

4

5

6

7

8

publicinterfaceSubject{

// 注册观察者

voidaddObserver(Observerobserver);

// 删除观察者

voiddeleteObserver(Observerobserver);

// 通知观察者

voidnotifyObservers();

}

接下来就是具体的实现类了,先来一个MessageCenter,是被观察者,用来给观察者发送消息的:

public class MessageCenter implements Subject {

private final CopyOnWriteArraySet observers = new CopyOnWriteArraySet<>();

private String mMessage;

@Override

public void addObserver(Observer observer) {

if (!observers.contains(observer)) {

observers.add(observer);

}

}

@Override

public void deleteObserver(Observer observer) {

observers.remove(observer);

}

@Override

public void notifyObservers() {

for (Observer observer : observers) {

observer.update(mMessage);

}

}

public void sendMessage(String message) {

mMessage = message;

notifyObservers();

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

publicclassMessageCenterimplementsSubject{

privatefinalCopyOnWriteArraySetobservers=newCopyOnWriteArraySet<>();

privateStringmMessage;

@Override

publicvoidaddObserver(Observerobserver){

if(!observers.contains(observer)){

observers.add(observer);

}

}

@Override

publicvoiddeleteObserver(Observerobserver){

observers.remove(observer);

}

@Override

publicvoidnotifyObservers(){

for(Observerobserver:observers){

observer.update(mMessage);

}

}

publicvoidsendMessage(Stringmessage){

mMessage=message;

notifyObservers();

}

}

然后再来一个观察者的具体实现:

public class DotaPlayer implements Observer {

public String playerName;

@Override

public void update(String message) {

System.out.println("DotaPlayer-" + playerName + "接收到信息:" + message);

}

}

1

2

3

4

5

6

7

8

publicclassDotaPlayerimplementsObserver{

publicStringplayerName;

@Override

publicvoidupdate(Stringmessage){

System.out.println("DotaPlayer-"+playerName+"接收到信息:"+message);

}

}

最后就是实际的调用了:

DotaPlayer playerA = new DotaPlayer();

playerA.playerName = "甲";

DotaPlayer playerB = new DotaPlayer();

playerB.playerName = "乙";

MessageCenter messageCenter = new MessageCenter();

messageCenter.addObserver(playerA);

messageCenter.addObserver(playerB);

messageCenter.sendMessage("圣剑代表了孤注一掷、背水一战的勇气……");

messageCenter.sendMessage("兄弟们,这波我很强,因为我有BKB!");

1

2

3

4

5

6

7

8

9

DotaPlayerplayerA=newDotaPlayer();

playerA.playerName="甲";

DotaPlayerplayerB=newDotaPlayer();

playerB.playerName="乙";

MessageCentermessageCenter=newMessageCenter();

messageCenter.addObserver(playerA);

messageCenter.addObserver(playerB);

messageCenter.sendMessage("圣剑代表了孤注一掷、背水一战的勇气……");

messageCenter.sendMessage("兄弟们,这波我很强,因为我有BKB!");

看一下运行结果:

System.out: DotaPlayer-甲接收到信息:圣剑代表了孤注一掷、背水一战的勇气……

System.out: DotaPlayer-乙接收到信息:圣剑代表了孤注一掷、背水一战的勇气……

System.out: DotaPlayer-甲接收到信息:兄弟们,这波我很强,因为我有BKB!

System.out: DotaPlayer-乙接收到信息:兄弟们,这波我很强,因为我有BKB!

在Android中的应用

观察者模式在Android里的运用十分广泛,Framework层中的观察者模式随处可见,而在很多第三方库中也有使用。

BroadcastReceiver

BroadcastReceiver就是一个十分典型的观察者模式,注册广播就是BroadcastReceiver这个观察者把自己添加到了被观察者那里(广播管理中心),然后被观察者发送某个广播时,只有注册了该广播的BroadcastReceiver才能接收到,最终在onReceive回调里收到广播再进行其他处理。

各种各样的Listener

最熟悉的当然是View. setOnClickListener这个流程了,setOnClickListener的参数OnClickListener本身就是一个接口,注册后,当发生点击事件时,View中的performClick()方法被调用,在该方法中通过mOnClickListener.onClick实现了回调。

各类Adapter

ListView、RecyclerView、ViewPager等的Adapter中,都有一个mObservable,它们归根结底都是android.database. Observable类的实现。当数据发生变化时,我们调用notifyDataSetChanged方法,最终就要依赖mObservable.notifyChanged()方法来实现数据刷新。

RxJava

这个库的强大相信很多人都有所了解。它可以很方便的实现链式调用,在主线程和其他子线程之间的切换十分便捷,在RxJava里观察者模式可以说是它的根本,才能实现如此方便的线程管理与数据流管理。代码分析就不上了,太多了,日后单独分析吧。

总结

观察者模式的优点还是比较明显的,耦合度较低,且被观察者只负责发出通知,通知都有谁接收、接收后做什么事情,一概不问。但也有可能会造成一个严重的问题,因为在notifyObservers方法里会对所有的观察者进行通知,如果观察者数量较多,甚至在update方法里执行了耗时操作,那么就有可能造成很严重的性能问题。

也有人把观察者模式与发布订阅模式(Publish-Subscribe pattern)划等号,认为这两者是一种设计模式。但实际上二者有一定的区别,从某种意义上说,发布订阅模式是解耦更彻底的一种特殊的观察者模式,但并不能直接判断二者孰好孰坏,还是要根据实际需求来选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值