Java设计模式中的观察者模式
作者:非凡的小笨鱼 时间:2021-08-22 01:27:20
一.介绍
观察者模式(Observer Pattern)属于行为型模式。定义了对象之间的一对多依赖,让多个观察者同时监听某一个主题对象,类似于广播机制,只需要分发广播,感兴趣的对象自动接收该广播。我们平常所说的Observer、Listener、Hook、Callback都和这个模式有关
二.场景约束
小孩(Baby)哭的时候会通知到爸爸(Dad)和妈妈(Mum),爸爸妈妈会对此采取不同的行为
三.UML类图
版本一
版本二
新增事件类将观察者与主题解耦,观察者可以根据不同的事件执行不同的操作,也可以直接对事件源进行操作
四.示意代码(版本一)
业务代码
//抽象观察者
public interface Observer {
void action();
}
//抽象主题
abstract class Subject{
protected List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public abstract void notifyObserver();
}
//具体主题-被观察者
class Baby extends Subject{
@Override
public void notifyObserver() {
System.out.println("baby cry");
observers.forEach(Observer::action);
}
}
//具体观察者
class Dad implements Observer {
@Override
public void action() {
System.out.println("dad feed baby");
}
}
//具体观察者
class Mum implements Observer {
@Override
public void action() {
System.out.println("mum hug baby");
}
}
客户端
public class Client {
public static void main(String[] args) {
Baby baby = new Baby();
baby.addObserver(new Mum());
baby.addObserver(new Dad());
baby.notifyObserver();
}
}
五.示意代码(版本二)
//抽象观察者
public interface Observer {
void action(Event event);
}
//抽象主题
abstract class Subject {
protected List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public abstract void notifyObserver();
}
//具体主题-被观察者
class Baby extends Subject {
@Override
public void notifyObserver() {
System.out.println("baby cry");
CryEvent cryEvent = new CryEvent(new Date().getTime(), this);
observers.forEach(observer -> observer.action(cryEvent));
}
}
//抽象事件
abstract class Event {
public abstract Object getSource();
}
//具体事件
class CryEvent extends Event {
public long when;
Baby source;
public CryEvent(long when, Baby source) {
this.when = when;
this.source = source;
}
@Override
public Baby getSource() {
return source;
}
}
//具体观察者
class Dad implements Observer {
@Override
public void action(Event event) {
System.out.println("dad feed baby");
if(event.getSource() instanceof Baby){
System.out.println("dad对事件源进行处理");
}
}
}
//具体观察者
class Mum implements Observer {
@Override
public void action(Event event) {
System.out.println("mum hug baby");
if(event.getSource() instanceof Baby){
System.out.println("mum对事件源进行处理");
}
}
}
客户端
public class Client {
public static void main(String[] args) {
Baby baby = new Baby();
baby.addObserver(new Dad());
baby.addObserver(new Mum());
baby.notifyObserver();
}
}
六.观察者模式与发布订阅模式
发布订阅模式
发布者不会直接通知订阅者
发布者与订阅者完全解耦
观察者模式
主题要自己通知(notify)观察者
主题与观察者松耦合
七.优点
符合依赖倒置原则(观察者与主题都依赖于抽象)
降低耦合(主题与观察者之间的耦合关系)
八.在JDK中的典型应用
在java.awt包下有很多观察者模式的身影,先来看下简单的UML类图
主题角色:java提供的组件类(以Button为例) 观察者角色:java提供的事件监听(各种Listener) 事件角色:鼠标事件、键盘事件等等
再来看看一个小demo 在窗口中添加一个按钮,给按钮添加上鼠标与键盘的相关事件,当点击按钮或者按下键盘的时候在控制台打印相应的语句
public class MainFrame extends JFrame {
public MainFrame() throws HeadlessException {
//定义一个具体主题
Button button = new Button("click");
//给主题添加观察者(鼠标监听)
button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
//MouseEvent就是具体事件
System.out.println("按钮被点击");
}
});
//给主题添加观察者(键盘监听)
button.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
//KeyEvent就是具体事件
System.out.println("按下" + e.getKeyChar());
}
});
add(button);
setSize(100,100);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public static void main(String[] args) {
new MainFrame();
}
}
这里的KeyAdapter与MouseAdapter使用的是适配器模式
来源:https://blog.csdn.net/a347635191/article/details/122393104
标签:Java,观察者模式,设计模式
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
mybatis like模糊查询特殊字符报错转义处理方式
2023-09-02 21:14:54
JavaWeb后台购物车类实现代码详解
2023-11-09 23:11:26
springboot 通过代码自动生成pid的方法
2023-11-27 02:54:57
![](https://img.aspxhome.com/file/2023/6/60366_0s.png)
详解Java线程池队列中的延迟队列DelayQueue
2023-08-30 01:22:04
Java数据结构及算法实例:三角数字
2023-08-24 17:52:25
java web中图片验证码功能的简单实现方法
2023-06-07 13:30:53
Java集合TreeSet用法详解
2023-11-10 22:53:34
![](https://img.aspxhome.com/file/2023/4/59354_0s.jpg)
Java中常见的编码集问题总结
2023-11-29 01:40:04
![](https://img.aspxhome.com/file/2023/5/60115_0s.png)
Java冒泡排序及优化介绍
2023-11-11 13:05:51
Java与C++分别用递归实现汉诺塔详解
2021-10-23 01:28:59
![](https://img.aspxhome.com/file/2023/7/62237_0s.png)
android中使用SharedPreferences进行数据存储的操作方法
2023-06-16 17:37:42
![](https://img.aspxhome.com/file/2023/1/83531_0s.png)
SpringBoot异常处理器的使用与添加员工功能实现流程介绍
2021-10-21 19:24:23
![](https://img.aspxhome.com/file/2023/8/60908_0s.png)
如何实现Spring Event(异步事件)
2023-08-23 05:06:47
Android Flutter中Offstage组件的使用教程详解
2023-08-20 01:01:44
java利用数组随机抽取幸运观众
2023-11-11 11:14:33
![](https://img.aspxhome.com/file/2023/0/59400_0s.jpg)
idea maven pom不自动更新的解决方法
2021-11-19 14:56:46
![](https://img.aspxhome.com/file/2023/9/62209_0s.jpg)
Java实现去除文档阴影的示例代码
2023-08-31 11:45:48
![](https://img.aspxhome.com/file/2023/5/58415_0s.png)
Java使用Collections工具类对List集合进行排序
2022-10-12 23:59:12
java 中clone()的使用方法
2023-03-31 12:11:37
SpringBoot项目在IntelliJ IDEA中如何实现热部署
2023-10-29 13:30:22
![](https://img.aspxhome.com/file/2023/4/58584_0s.png)