java设计模式学习之【观察者模式】

文章目录

引言

想象你在一个在线拍卖会上竞标一件珍贵的艺术品。每当有人出价更高,系统都会立即通知你。这个实时更新机制使你可以做出快速反应。这种模式,在软件开发中称为观察者模式,是一种广泛应用于实现事件驱动系统的设计模式。

观察者模式简介

定义与用途

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了对象间的一种一对多的依赖关系,使得每当一个对象改变状态时,其所有依赖者都会得到通知并自动更新。这种模式用于构建松散耦合的系统,其中一个对象的改变可以影响一个或多个其他对象,而无需对象之间有紧密的关联。

实现方式

实现观察者模式通常涉及以下几个关键组件:

  • 主题(Subject):持有观察者的列表,并提供添加、删除观察者的接口。
  • 观察者(Observer):为那些在主题状态发生变化时需获得通知的对象定义一个更新接口。
  • 具体主题(Concrete Subject):状态发生改变时,向所有注册的观察者发出通知。
  • 具体观察者(Concrete Observer):实现观察者接口的类,定义当接收到主题通知时如何更新自己。

使用场景

观察者模式适用于以下场景:

  • 当一个对象的改变需要同时改变其他对象,而不知道具体有多少对象待改变时。
  • 当一个对象必须通知其他对象,而它又不能假定其他对象是谁。

例如:

  • 股票市场应用:股票价格更新时,所有关注该股票的投资者都会收到通知。
  • 社交媒体订阅:用户在社交媒体上订阅某个名人或主题,当有更新时用户可以立即收到通知。
  • 电子邮件系统:当新邮件到达时,电子邮件客户端会通知用户。

优势与劣势

  • 优势
    • 支持简单的广播通信,解除对象间的紧密耦合。
    • 支持实时通知,对象状态改变时,观察者立即得到更新。
  • 劣势
    • 如果观察者非常多,通知会花费较多时间。
    • 如果观察者和主题之间有循环依赖,可能导致系统崩溃。

在Spring框架中的应用

Spring框架广泛应用了观察者模式,尤其是在事件驱动模型中。以下是一些具体应用:

1. 事件监听
Spring的事件监听机制就是观察者模式的一个例子。当一个事件被触发时,所有监听该事件的监听器都会收到通知。例如,ApplicationContext 发布了各种类型的事件,如 ContextRefreshedEvent,应用中的各个部分可以通过实现 ApplicationListener 来响应这些事件。

2. WebSocket
在Spring中,WebSocket的实现也使用了观察者模式。服务器和客户端之间的通信建立在这种模式上,当一方发送消息时,另一方可以即时接收和响应。

观察者示例

这个示例展示了观察者模式在Java中的实现。观察者模式是一种行为设计模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

步骤 1:创建主题类

java 复制代码
private List<Observer> observers = new ArrayList<Observer>();
   private int state;

   public int getState() {
      return state;
   }

   public void setState(int state) {
      this.state = state;
      notifyAllObservers();
   }

   public void attach(Observer observer){
      observers.add(observer);		
   }

   public void notifyAllObservers(){
      for (Observer observer : observers) {
         observer.update();
      }
   } 	

Subject 是持有观察者列表的类,并提供了方法来添加和删除观察者。当它的状态改变时,它会通知所有观察者。

步骤 2:创建观察者类

java 复制代码
public abstract class Observer {
   protected Subject subject;
   public abstract void update();
}

Observer 是一个抽象类,为所有具体的观察者定义了一个更新接口。每个具体的观察者都需要实现这个接口。

步骤 3:创建具体的观察者类

java 复制代码
public class BinaryObserver extends Observer{

   public BinaryObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }

   @Override
   public void update() {
      System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) ); 
   }
}

BinaryObserver 是一个具体的观察者,它将主题的状态以二进制形式输出。

java 复制代码
public class OctalObserver extends Observer{

   public OctalObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }

   @Override
   public void update() {
     System.out.println( "Octal String: " + Integer.toOctalString( subject.getState() ) ); 
   }
}

OctalObserver 是另一个具体的观察者,它将主题的状态以八进制形式输出。

java 复制代码
public class HexaObserver extends Observer{

   public HexaObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }

   @Override
   public void update() {
      System.out.println( "Hex String: " + Integer.toHexString( subject.getState() ).toUpperCase() ); 
   }
}

HexaObserver 是第三个具体的观察者,它将主题的状态以十六进制形式输出。

步骤 4:使用主题和具体的观察者对象

java 复制代码
public class ObserverPatternDemo {
   public static void main(String[] args) {
      Subject subject = new Subject();

      new HexaObserver(subject);
      new OctalObserver(subject);
      new BinaryObserver(subject);

      System.out.println("第一次状态改变: 15");	
      subject.setState(15);
      System.out.println("第二次状态改变: 10");	
      subject.setState(10);
   }
}

在这个演示类中,我们创建了一个主题对象和三个观察者对象。然后我们改变了主题的状态,观察者会自动更新并打印出新的状态。

这个示例演示了观察者模式如何在软件设计中用于创建灵活的通知机制,当对象状态改变时,所有依赖于它的对象都会自动更新。这种模式使得对象之间的通信变得更加简洁和松耦合。

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址

https://github.com/RuofeiSun/lf-23Pattern

相关推荐
阿伟*rui2 小时前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel
XiaoLeisj4 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck4 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei4 小时前
java的类加载机制的学习
java·学习
Yaml45 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~6 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616886 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7896 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java7 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
睡觉谁叫~~~7 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust