观察者模式
学习容易,坚持不易,如果你坚持看完,会发现设计模式如此简单~
目录
-
引子
-
认识观察者模式
-
我们先来看看微信公众号和用户之间的关注是怎么回事?
-
发布者+订阅者=观察者模式
-
-
观察者模式的原理
-
定义
-
优点
-
缺点
-
结构图
-
主要角色
-
-
如何创建观察者模式
-
总结
-
思维导图
引子
在现实世界中,很多事物并不是独立存在的,其中一个事物的改变可能会导致一个或多个其他对象行为的改变;
在code世界也是一样,多个对象之间存在依赖关系,当一个对象状态发生改变时,所有依赖于他的对象都会得到通知并自动更新;
code世界中有个设计模式可以帮助我们更好的实现这个行为,对,他就是观察者模式;「本文以观察者模式来模拟微信公众号文章的发送与接收。」
认识观察者模式
我们先来看看微信公众号和用户之间的关注是怎么回事?
-
微信公众号的业务就是发布文章;
-
用户关注微信公众号,只要公众号有新文章的发布,就会给你推送;
-
当你不想再看该公众号文章时,你只要取消关注,你就再也不会收到新的文章;
-
只要公众号一直存在,就会有用户进行关注和取关操作;
发布者+订阅者=观察者模式
当我们知道微信公众号和用户之间的关系之后我们就大概知道什么是观察者模式;「公众号为主题,用户为观察者」
观察者模式的原理
定义:观察者模式指多个对象之间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖他的对象就会收到通知,并进行自动更新;又称为:「发布-订阅模式」
优点:
-
降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
-
目标与观察者之间建立了一套触发机制。
缺点:
-
目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
-
当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
结构图
主要角色
-
「抽象主题(Subject)」 角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
-
「具体主题(Concrete Subject)」 角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
-
「抽象观察者(Observer)」 角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
-
「具体观察者(Concrete Observer)」 角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
如何创建观察者模式
这里以公众号发布和用户订阅及收到文章举例
「Myy:」 我想设计一个简单的消息推送及接收,该观察者模式实现呢?
「观察者:」 我们结合定义和主要角色来思考;公众号则是那个“一“,即发布者,用户则是依赖于公众号的“多”及观察者;
当公众号发布新的文章,这时所有关注他的用户将接收到文章;
这时,管理用户行为的角色
,就作为抽象主题的角色
,成为抽象目标类,内部提供了
-
保存观察者(用户)对象的集合类
-
增加(关注)、删除(取关)观察者的方法
-
通知所有观察者的抽象方法 以下用代码进行实现
/**
* @包名:com.myy.review.observer
* @类描述:抽象目标类
* @创建人:myy
* @创建时间:2020/7/10 16:37
* @version:V1.0
*/
public abstract class UserManager {
//一个用于保存订阅者的集合
protected List<User> users = new ArrayList<>();
//用户订阅(用户的关注)
public void subscribe(User user){
users.add(user);
System.out.println(user.getUsername()+",关注了你的公众号");
}
//用户取消订阅(用户的取关)
public void unSubscribe(User user){
users.remove(user);
System.out.println(user.getUsername()+",取关了你的公众号");
}
//新文章发布时通知所有用户的抽象方法
public abstract void notifyUser();
}
公众号发布新文章
为具体主题目标类
,实现了抽象目标中的通知方法,当有新文章发布时,通知所有关注的用户对象,用以下代码进行实现
/**
* @包名:com.myy.review.observer
* @类描述:具体主题
* @创建人:myy
* @创建时间:2020/7/10 16:51
* @version:V1.0
*/
public class SendEvent extends UserManager {
@Override
public void notifyUser() {
//有新文章发布时,循环关注的用户的进行通知,用户接收文章
for (User user:users) {
user.receive();
}
}
}
监听发送的接口
即为抽离观察者角色
,包含了一个实现接收的方法
,监听文章发送并使用户进行被动接收,用以下代码进行实现
/**
* @包名:com.myy.review.observer
* @类描述:抽象观察者
* @创建人:myy
* @创建时间:2020/7/10 16:51
* @version:V1.0
*/
public interface SendListener {
//发布新文章时,推送给用户,用户被动接收
void receive();
}
用户
即为具体观察者角色
,实现了抽象观察者中定义的抽象方法,当有新文章发布时,自动更新自身状态,用以下代码实现:
/**
* @包名:com.myy.review.observer
* @类描述:具体观察者
* @创建人:myy
* @创建时间:2020/7/10 16:40
* @version:V1.0
*/
public class User implements SendListener {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public User(String username) {
this.username = username;
}
@Override
public void receive() {
System.out.println("用户:"+username+",接收到新的文章");
}
}
代码写到这里就完成了,以下进行测试
,测试类如下:
/**
* @包名:com.myy.review.observer
* @类描述:测试公众号发送
* @创建人:myy
* @创建时间:2020/7/10 16:59
* @version:V1.0
*/
public class ObserverTest {
public static void main(String[] args) {
System.out.println("-------用户开始关注公众号-------");
UserManager userManager = new SendEvent();
User user1 = new User("小花");
userManager.subscribe(user1);
User user2 = new User("马珍珍");
userManager.subscribe(user2);
System.out.println("-------公众号文章开始推送,并通知用户-------");
userManager.notifyUser();
}
}
测试结果
如下展示:
总结
观察者模式由抽象主题(Subject)角色、 具体主题(Concrete Subject)角色、 抽象观察者(Observer)角色、 具体观察者(Concrete Observer)角色四个角色组成,设计时,我们只需要将事件的发生按角色进行划分,抽离出发布者与观察者,这样我们可以更简单快速的实现观察者模式。
思维导图
我是马珍珍,一个专注于Java后端研发的小姑娘,觉得文章有帮助到你的,关注、点赞,哦~,关注微信公众号:JAVA程序人生,首次发布,同步更新