观察者模式
上一篇文章中我们介绍了策略模式,这一篇我们主要来介绍一下观察者模式。
1、定义
观察者模式 定义了对象之间一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
观察者模式的定义很好理解,定义了一对多的依赖,当一个对象发生改变时,依赖它的对象都能够收到通知并执行相应的更新操作,下面我们通过一个案例来详细讲解一下观察者模式。
2、观察者模式案例
2.1、需求
假设我们做了一个类似于微信的软件,这个软件中有多个用户,用户可以自行关注一些订阅号,当某个订阅号更新的时候,关注该订阅号的用户都能够收到相关消息,用户也可以取消关注订阅号,用户取消后将不再收到订阅号的消息。
2.2、第一种实现方式
看到这个需求后我们最先想到的实现方式是:先定义一系列的用户类,每个用户类中都有更新消息的方法,然后再定义一个订阅号类,在订阅号类中引入用户类,只有关注了此公众号的用户类才会被引入,当订阅号有新消息时调用每个用户类的更新方法即可。下面我们就是用代码来实现这个想法,我们首先定义几个用户类,假设这个软件中有三个用户:普通用户、企业用户和VIP用户:
/**普通用户*/
public class GeneralUser {
public void update(String message) {
System.out.println("普通用户收到消息:" + message);
}
}
/**企业用户*/
public class EnterpriseUser {
public void update(String message) {
System.out.println("企业用户收到消息:" + message);
}
}
/**VIP用户*/
public class VipUser {
public void update(String message) {
System.out.println("会员收到消息:" + message);
}
}
这里每个用户都有一个更新方法update(),现在我们再定义一个订阅号类:
public class Subscription {
String message;
public void sendMessage() {
GeneralUser generalUser = new GeneralUser();
EnterpriseUser enterpriseUser = new EnterpriseUser();
VipUser vipUser = new VipUser();
generalUser.update(message);
enterpriseUser.update(message);
vipUser.update(message);
}
}
这个类中只定义了一个属性message表示消息、一个发送消息方法sendMessage(),当订阅号更新后会调用sendMessage()来给用户发送消息,在sendMessage()方法中调用了各个用户的更新方法update()用于收取消息。接下来我们就可以写一个测试方法进行测试了:
public static void main(String[] args) {
Subscription subscription = new Subscription();
subscription.message = "测试消息";
subscription.sendMessage();
}
运行结果:
普通用户收到消息:测试消息
企业用户收到消息:测试消息
会员收到消息:测试消息
可以看到,当订阅号有更新后,用户都收到了消息,这样的实现方式看似实现了需求中规定的功能,但实际上这种方式是存在问题的:
- 如果软件用户增加了,比如新来了一位黄金会员关注了此订阅号,那么我们就需要修改Subscription的sendMessage()方法来让黄金会员也能够收到消息,如果再来一位铂金会员,又需要添加新的用户信息,这样每次新增一位关注用户都需要修改一次Subscription的sendMessage()方法,这样代码会越来越臃肿,而且订阅号与用户之间紧紧耦合在一起,难以维护;
- 需求中提到,用户可以取消关注,取消关注后将不再收到消息,在上述的实现方式中要使用户不再收到消息,唯一的办法就是删除Subscription的sendMessage()方法中相关用户信息,还是需要改动程序。
总的来说,上述1、2两点描述的是相同的问题,上述实现方式无法实现动态地增删用户,每次增加和删除用户时都需要手动修改Subscription的sendMessage()方法,这样使代码的可扩展性变得很差,要解决这个问题我们可以使用观察者模式来重新设计一下。
2.3、观察者模式实现方式
现在我们通过观察者模式的定义来分析一下如何实现需求,观察者模式定义了对象之间一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。在这个案例中,订阅号的消息就类似于对象,而关注订阅号的用户就相当于对象的依赖者,每次订阅号更新的时候,用户都能收到消息并进行更新,这样我们就可以定义一个类Subscription表示订阅号,其中有通知用户的功能。另外,需求中还提到用户可以关注和取消关注,也就是说订阅号类中需要有新增和删除用户的功能。我们可以将订阅号类中的方法抽象为一个接口Subject,其中包含新增、删除观