原文网址:
简介
说明
本文用示例介绍观察者模式的用法。
观察者模式的含义
模式的角色
- 抽象被观察者角色(Subject) //也就是一个抽象主题
- 它把所有观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。
- 象主题提供一个接口,可以增加和删除观察者角色。
- 一般用一个抽象类和接口来实现。
- 抽象观察者角色(Observer)
- 为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
- 具体被观察者角色(ConcernSubject)
- 也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
- 具体观察者角色(ConcernObserver)
- 实现抽象观察者角色所需要的更新接口,使本身的状态与主题的状态相协调
实例
项目的所有文件
主题(公众号)
抽象主题(公众号)
package com.example.a.subject;
import com.example.a.observer.Observer;
/**
* 抽象被观察者(主题): 公众号
*/
public interface OfficialAccount {
/**
* 关注
* @param observer 用户
*/
void follow(Observer observer);
/**
* 取消关注
* @param observer 用户
*/
void unfollow(Observer observer);
/**
* 公众号通知
* @param message 通知的内容
*/
void notify(String message);
}
具体主题(某个公众号)
package com.example.a.subject;
import com.example.a.observer.Observer;
import java.util.ArrayList;
import java.util.List;
/**
* 具体被观察者(主题): Knife公众号
*/
public class KnifeOfficialAccount implements OfficialAccount {
private List<Observer> list;
public KnifeOfficialAccount() {
this.list = new ArrayList<>();
}
@Override
public void follow(Observer observer) {
list.add(observer);
}
@Override
public void unfollow(Observer observer) {
list.remove(observer);
}
@Override
public void notify(String message) {
System.out.println("Knife公众号发了新消息:" + message);
for (Observer observer : list) {
observer.operate(message);
}
}
public List<Observer> getList() {
return list;
}
public void setList(List<Observer> list) {
this.list = list;
}
}
观察者(用户)
抽象观察者(用户)
package com.example.a.observer;
/**
* 抽象观察者: 用户
*/
public interface Observer {
/**
* 用户收到通知后的操作
*/
void operate(String message);
}
具体观察者(某个用户)
package com.example.a.observer;
/**
* 具体观察者: 用户
*/
public class UserObserver implements Observer {
private String userName;
public UserObserver(String userName) {
this.userName = userName;
}
@Override
public void operate(String message) {
System.out.println("用户【" + this.userName + "】接收新消息:" + message);
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
测试
测试类
package com.example.a;
import com.example.a.observer.Observer;
import com.example.a.observer.UserObserver;
import com.example.a.subject.KnifeOfficialAccount;
import com.example.a.subject.OfficialAccount;
public class Demo {
public static void main(String[] args) {
Observer user1 = new UserObserver("张三");
Observer user2 = new UserObserver("李四");
Observer user3 = new UserObserver("王五");
OfficialAccount officialAccount = new KnifeOfficialAccount();
officialAccount.follow(user1);
officialAccount.follow(user2);
officialAccount.follow(user3);
officialAccount.notify("本文介绍常见的Java面试题");
System.out.println("=================================================");
officialAccount.unfollow(user2);
System.out.println("李四取消了订阅");
System.out.println("=================================================");
officialAccount.notify("本文介绍察者设计模式");
}
}
结果
Knife公众号发了新消息:本文介绍常见的Java面试题
用户【张三】接收新消息:本文介绍常见的Java面试题
用户【李四】接收新消息:本文介绍常见的Java面试题
用户【王五】接收新消息:本文介绍常见的Java面试题
=================================================
李四取消了订阅
=================================================
Knife公众号发了新消息:本文介绍察者设计模式
用户【张三】接收新消息:本文介绍察者设计模式
用户【王五】接收新消息:本文介绍察者设计模式
SpringBoot的观察者模式
实际上,我们可以直接使用Spring的事件监听机制,它就是观察者模式,用起来更方便。见:SpringBoot--事件监听机制--使用/实例/原理_IT利刃出鞘的博客-CSDN博客
JDK的观察者模式
简介
在 Java 中,通过 java.util.Observable 类和 java.util.Observer 接口定义了观察者模式,只要实现它们的子类就可以编写观察者模式实例。
1. Observable
Observable 类是抽象目标类(被观察者),它有一个 Vector 集合成员变量,用于保存所有要通知的观察者对象,下面来介绍它最重要的 3 个方法。
- void addObserver(Observer o) 方法:用于将新的观察者对象添加到集合中。
- void notifyObservers(Object arg) 方法:调用集合中的所有观察者对象的 update方法,通知它们数据发生改变。通常越晚加入集合的观察者越先得到通知。
- void setChange() 方法:用来设置一个 boolean 类型的内部标志,注明目标对象发生了变化。当它为true时,notifyObservers() 才会通知观察者。
2. Observer
Observer 接口是抽象观察者,它监视目标对象的变化,当目标对象发生变化时,观察者得到通知,并调用 update 方法,进行相应的工作。
示例
警察抓小偷也可以使用观察者模式来实现,警察是观察者,小偷是被观察者。
小偷是一个被观察者,所以需要继承Observable类
package com.example.a;
import java.util.Observable;
public class Thief extends Observable {
private String name;
public Thief(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void steal() {
System.out.println("小偷-" + name + ":我偷东西了");
super.setChanged(); //changed = true
super.notifyObservers();
}
}
警察是一个观察者,所以需要实现Observer接口
package com.example.a;
import java.util.Observable;
import java.util.Observer;
public class Policemen implements Observer {
private String name;
public Policemen(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public void update(Observable observable, Object arg) {
System.out.println("警察-" + name + ": "
+ ((Thief) observable).getName()
+ ",我已经盯你很久了,终于抓到你了");
}
}
测试
package com.example.a;
public class Demo {
public static void main(String[] args) {
//创建小偷对象
Thief t = new Thief("老王");
//创建警察对象
Policemen p = new Policemen("小李");
//让警察盯着小偷
t.addObserver(p);
//小偷偷东西
t.steal();
}
}
结果
小偷-老王:我偷东西了
警察-小李: 老王,我已经盯你很久了,终于抓到你了
其他网址
Java设计模式之观察者模式_贺兰山的那个脉的博客-CSDN博客
设计模式-观察者模式_逍遥壮士-CSDN博客