在 Java 中,观察者模式的实现通常涉及两个关键角色:被观察者(Observable)和观察者(Observer)。
抽象被观察者(Subject):定义了一个接口,包含了注册观察者、删除观察者、通知观察者等方法。
具体被观察者(ConcreteSubject):实现了抽象被观察者接口,维护了一个观察者列表,并在发生改变时通知所有注册的观察者。
抽象观察者(Observer):定义了一个接口,包含了更新状态的方法。
具体观察者(ConcreteObserver):实现了抽象观察者接口,存储了需要观察的被观察者对象,并在被观察者状态发生改变时进行相应的处理。
下面展示被观察者发送变动,通知观察者的代码DEMO,以开发项目组加入和删除员工为示例
1-1 UML类图展示
1- 被观察者
被观察者(Subject)是一个类,提供方法用于添加、移除和通知观察者
public abstract class Subject {
//定义项目组名称
public String projectName;
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
// 添加观察者
public abstract void attach(ObserverUtil observerUtil);
//删除观察者
public abstract void detach(ObserverUtil observerUtil);
// 通知观察者们
public abstract void notifyAllObservers(String name);
}
2- 被观察者的具体实现
public class SubjectImpl extends Subject {
//定义一个观察者集合用于存储所有观察者对象
public List<ObserverUtil> observerUtils = new ArrayList<ObserverUtil>();
public SubjectImpl(String projectName) {
System.out.println(projectName + "JAVA项目组,组建成功!");
this.setProjectName(projectName);
}
//添加观察者
@Override
public void attach(ObserverUtil observerUtil) {
System.out.println(observerUtil.getName() + "加入公司");
observerUtils.add(observerUtil);
}
//删除观察者
@Override
public void detach(ObserverUtil observerUtil) {
System.out.println(observerUtil.getName() + "删除数据库,被开除");
observerUtils.remove(observerUtil);
}
//通知观察者们
@Override
public void notifyAllObservers(String name) {
System.out.println(this.projectName + "公司通报,员工" + name + "违反公司规章将被开除");
for (ObserverUtil en : observerUtils) {
en.update(en.getName());
}
}
}
3-观察者
public abstract class ObserverUtil {
public Subject subject;
public abstract String getName();
//接受通知
public abstract void update(String name);
}
4-观察者的具体实现
public class User extends ObserverUtil {
private String name;
public User(String name){
this.name = name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public void update(String name) {
System.out.println(name + "接受到消息---->!");
}
}
5-编写测试用例
@SpringBootTest
class DemoApplicationTests {
@org.junit.jupiter.api.Test
void contextLoads() {
// 定义观察目标对象
Subject subject = new SubjectImpl("JAVA电商项目组");
// 定义4个观察者对象
ObserverUtil user1, user2, user3, user4;
user1 = new User("雷小军");
user2 = new User("乔小布斯");
user3 = new User("刘强西");
//加入了项目组
subject.attach(user1);
subject.attach(user2);
subject.attach(user3);
//雷小军摸鱼被开除,通知所有人
subject.notifyAllObservers("雷小军");
/**
开除雷小军后面再通知
*/
//雷小军被开除,已经走了,再通知所有人
subject.detach(user1);
subject.notifyAllObservers("雷小军");
}
}
结果展示
JAVA电商项目组JAVA项目组,组建成功!
雷小军加入公司
乔小布斯加入公司
刘强西加入公司
JAVA电商项目组公司通报,员工雷小军违反公司规章将被开除
雷小军接受到消息---->!
乔小布斯接受到消息---->!
刘强西接受到消息---->!
删除雷小军后通知结果,雷小军将不收到信息
JAVA电商项目组JAVA项目组,组建成功!
雷小军加入公司
乔小布斯加入公司
刘强西加入公司
JAVA电商项目组公司通报,员工雷小军违反公司规章将被开除
乔小布斯接受到消息---->!
刘强西接受到消息---->!