【设计模式深度剖析】【10】【行为型】【状态模式】

👈️上一篇:访问者模式    |   下一篇:解释器模式👉️

设计模式-专栏👈️


文章目录

  • 状态模式
  • 定义
    • 英文定义
    • 直译
    • 如何理解呢?
  • 状态模式的角色
    • Context(环境类)
    • State(抽象状态类)
    • ConcreteState(具体状态类)
    • 类图
    • 代码示例
  • 状态模式的应用
    • 优点
    • 缺点
    • 使用场景

状态模式

状态模式State Pattern)又称为状态对象(Objects for States)模式,该模式允许一个对象在其内部状态改变时改变其行为。

状态模式就像一部智能的“剧情播放器”,根据不同的“剧本”(状态)自动切换“演员”(行为),让系统“表演”出各种复杂且有序的行为。

定义

英文定义

The State Pattern allows an object to alter its behavior when its internal state changes. The object will appear to change its class.

直译

状态模式允许一个对象在其内部状态改变时改变其行为。这个对象看起来像是改变了它的类。

如何理解呢?

状态模式就像是一个智能的“状态机”,它可以管理一个对象的多种状态,并根据当前状态来执行相应的行为。

比如,我们可以把一个电梯看作是一个对象,它有三种状态:停止、运行和故障。

当电梯处于不同的状态时,它的行为也会不同。

例如,

当电梯处于停止状态时,它不会移动;

当电梯处于运行状态时,它可以响应乘客的上下行请求;

当电梯出现故障时,它会停止运行并发出警报。

通过使用状态模式,我们可以将这些状态和对应的行为封装在单独的类中,使得代码更加清晰和易于维护。

同时,当需要添加新的状态或修改某个状态的行为时,我们只需要修改对应的状态类,而不需要修改其他部分的代码,这使得系统具有很好的扩展性和可维护性。

当控制一个对象状态的条件表达式过于复杂时,状态模式可以将这些复杂的判断逻辑转移到表示不同状态的一系列类中,从而简化判断逻辑。

状态模式的角色

Context(环境类)

也称为上下文,它定义了客户端所感兴趣的接口,并且维护一个具体状态对象的实例。这个实例定义了当前状态。

State(抽象状态类)

这是一个抽象类或接口,用以封装与Context的一个特定状态相关的行为。

ConcreteState(具体状态类)

这是实现了State接口的类,每一个类实现了一个与Context的一个状态相关的行为。

类图

在这里插入图片描述

代码示例

package com.polaris.designpattern.list3.behavioral.pattern10.state.classicdemo;// 抽象状态类
interface State {void handleRequest(Context context);
}// 具体状态类A  
class StateA implements State {@Overridepublic void handleRequest(Context context) {System.out.println("StateA handling request");// 假设在StateA处理请求后,无条件地转移到StateB  context.setState(new StateB());}
}// 具体状态类B  
class StateB implements State {@Overridepublic void handleRequest(Context context) {System.out.println("StateB handling request");// 假设在StateB处理请求后,根据某个条件判断是否转回StateA  if (someConditionToCheck()) { // 这是一个假设的条件检查方法  context.setState(new StateA());System.out.println("State changed to A");} else {System.out.println("Remaining in State B");}}// 假设的条件检查方法  private boolean someConditionToCheck() {// 这里可以添加你的条件逻辑  // 例如,可以检查某个变量的值,或者模拟用户输入等  // 这里我们简单地返回一个固定值作为示例  return Math.random() < 0.5; // 50% 的概率返回 true  }
}// 环境类  
class Context {private State state;public Context() {// 初始状态设置为StateA  this.state = new StateA();}public void setState(State state) {this.state = state;}public void request() {// 委托给当前状态对象处理请求  state.handleRequest(this);}// Getter方法用于调试或日志记录(可选)  public State getState() {return state;}
}// 客户端代码  
public class Client {public static void main(String[] args) {Context context = new Context();// 客户端发送请求给Context  context.request(); // 输出 "StateA handling request",并转移到StateB  // 假设这里有一些业务逻辑,但这里没有额外的代码  // 再次发送请求以展示可能的状态变化  context.request(); // 输出 "StateB handling request",并根据条件判断是否转回StateA  // 第三次发送请求,以展示状态可能继续变化或保持不变  context.request(); // 输出将取决于StateB中的条件判断  // (可选)打印当前状态用于调试或日志记录  System.out.println("Current state: " + context.getState().getClass().getSimpleName());}
}/* Output:
StateA handling request
StateB handling request
State changed to A
StateA handling request
Current state: StateB
*///~

在上面的示例中,Context类代表了一个对象,它的行为可能会根据当前的状态(State)而变化。每个ConcreteState(这里是StateAStateB)都定义了在该状态下如何处理请求。当Context收到一个请求时,它会将请求委托给当前的状态对象去处理。状态对象在处理请求时,可能会改变Context的状态。

状态模式的应用

状态模式是一种行为型设计模式,它允许一个对象在其内部状态改变时改变其行为。简单来说,就是当某个对象有多种状态,并且不同状态下有不同的行为时,我们可以使用状态模式来管理这些状态和对应的行为。

优点

  1. 封装了状态的转换规则:状态模式将状态的转换逻辑封装在状态类中,使得代码更加清晰和易于管理。
  2. 简化条件语句:避免了使用大量的条件语句来判断对象的状态和行为,使得代码更加简洁和易于维护。
  3. 可维护性高:当需要添加新的状态或修改某个状态的行为时,只需要修改对应的状态类,而不需要修改其他部分的代码,符合开闭原则。
  4. 扩展性好:状态模式允许新的状态类很容易地加入到系统中,使得系统具有很好的扩展性。

缺点

  1. 增加系统复杂性:使用状态模式会增加系统中类和对象的个数,使得系统结构变得复杂。
  2. 对开闭原则的支持不足:虽然状态模式在一定程度上符合开闭原则,但当需要添加新的状态时,可能需要修改状态转换的代码,这可能会破坏开闭原则。
  3. 使用不当可能导致代码混乱:如果状态模式和具体业务逻辑结合不当,可能会导致代码结构混乱,增加维护难度。

使用场景

  1. 对象的行为取决于它的状态:当对象的行为会根据其内部状态的不同而发生变化时,可以使用状态模式。
  2. 状态转换逻辑复杂:当对象的状态转换逻辑非常复杂时,使用状态模式可以将这些逻辑封装在状态类中,使得代码更加清晰和易于维护。
  3. 避免使用大量的条件语句当代码中使用了大量的条件语句来判断对象的状态和行为时,可以考虑使用状态模式来简化代码。

👈️上一篇:访问者模式    |   下一篇:解释器模式👉️

设计模式-专栏👈️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/31164.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java | Leetcode Java题解之第169题多数元素

题目&#xff1a; 题解&#xff1a; class Solution {public int majorityElement(int[] nums) {int count 0;Integer candidate null;for (int num : nums) {if (count 0) {candidate num;}count (num candidate) ? 1 : -1;}return candidate;} }

SpringCloud微服务框架的原理及应用详解(一)

本系列文章简介&#xff1a; 随着云计算、大数据和物联网等技术的飞速发展&#xff0c;企业应用系统的规模和复杂度不断增加&#xff0c;传统的单体架构已经难以满足快速迭代、高并发、高可用性等现代业务需求。在这样的背景下&#xff0c;微服务架构应运而生&#xff0c;成为了…

Netdata介绍

前言 Netdata是一款用于Linux系统的实时性能监测工具&#xff0c;它提供了web界面的视角&#xff0c;使得用户可以通过可视化的方式清晰地了解系统和应用程序的实时状态。 Netdata具有以下几个显著特点&#xff1a; 实时性&#xff1a;Netdata能够实时监测系统和应用程序的性…

Android-Android Studio-FAQ

1 需求 2 接口 3 Android Studio xml布局代码补全功能失效问题 最终解决方案就是尝试修改compileSdk 为不同SDK版本来解决问题&#xff0c;将原本34修改为32测试会发现xml代码补全功能有效了&#xff01; 参考资料 Android Studio xml布局代码补全功能失效问题_android studi…

电压调整+无功优化!考虑泄流效应的风电场并网点电压系统侧增援调控方法程序代码!

前言 在发电侧能源结构转型的背景下&#xff0c;中国在可再生能源发电技术上的快速发展使得电网中风电并网比例不断增大。风能资源的有效利用缓解了电力紧张&#xff0c;但由于风速的不确定性&#xff0c;风电场引起的公共耦合点&#xff08;point of common coupling&#xf…

vue3项目使用Electron打包成exe的方法与打包报错解决

将vue3项目打包成exe文件方法 一、安装 1.安装electron npm install electron --save-devnpm install electron-builder --save-dev 2.在vue项目根目录新建文件index.js // index.js// Modules to control application life and create native browser window const { app…

Map-JAVA面试常问

1.HashMap底层实现 底层实现在jdk1.7和jdk1.8是不一样的 jdk1.7采用数组加链表的方式实现 jdk1.8采用数组加链表或者红黑树实现 HashMap中每个元素称之为一个哈希桶(bucket),哈希桶包含的内容有以下4项 hash值&#xff08;哈希函数计算出来的值&#xff09; Key value next(…

基于SSM+Jsp的水果销售管理网站

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

Linux 五种IO模型

注&#xff1a;还有一种信号驱动IO&#xff0c;使用较少暂不讨论&#xff1b; 一&#xff0c;区分阻塞、非阻塞和同步、异步 看了很多文章对这两组概念解释和对比&#xff0c;说的太复杂了&#xff0c;其实没必要&#xff0c;两句话就能说清楚。 首先&#xff0c;对于读数据rec…

探索监管沙箱在金融科技行业中的应用

一、引言 随着金融科技的快速发展&#xff0c;传统金融机构与科技企业之间的竞争也日趋激烈。为了平衡金融科技创新与风险防控&#xff0c;各国监管机构纷纷引入监管沙箱&#xff08;Regulatory Sandbox&#xff09;机制。监管沙箱作为一个受监督的安全测试区&#xff0c;允许金…

在超线程CPU上切换到另一个线程

在超线程CPU上切换到另一个线程&#xff0c;主要涉及到的是上下文切换的过程。超线程技术允许单个CPU核心同时执行多个线程&#xff0c;提高了CPU的并行计算效率。当需要从一个线程切换到另一个线程时&#xff0c;CPU会进行一系列的操作来确保线程之间的顺利切换。 首先&#…

Linux字节对齐小程序

#include <stdio.h> // 默认对齐 struct DefaultAligned { char c; int i; }; // 按1字节对齐 #pragma pack(push, 1) struct OneByteAligned { char c; int i; }; #pragma pack(pop) // 恢复之前的对齐设置 int mai…

linux基础 - 内核的基础概念

目录 零. 前言 一. 源码简介 二. 存储管理 物理内存管理&#xff1a; 虚拟内存管理&#xff1a; 内存分配与回收&#xff1a; 三. CPU 和进程管理 进程管理&#xff1a; CPU 管理&#xff1a; 四. 文件系统 文件系统的概念 常见的 Linux 文件系统类型 文件系统的工…

Python日志管理利器:如何高效管理平台日志

一、为什么需要日志管理&#xff1f; 日志是应用程序的重要组成部分&#xff0c;它记录了应用程序的运行状态、错误信息以及用户交互等关键信息。良好的日志管理可以帮助开发人员及时发现和解决问题&#xff0c;提高应用程序的稳定性和可靠性。 项目在本地开发调试时&#xf…

Redis 有序集合(sorted set)

Redis 有序集合(sorted set) 引言 Redis&#xff0c;作为一个高性能的键值对数据库&#xff0c;提供了多种数据结构来满足不同的需求。其中&#xff0c;有序集合&#xff08;sorted set&#xff09;是一种特别的数据结构&#xff0c;它不仅具有集合&#xff08;set&#xff0…

CSS 计数器

CSS 计数器 CSS 计数器是 CSS 中一个强大但经常被忽视的功能。它们允许开发者创建和管理计数器,这些计数器可以在文档中自动递增,非常适合用于编号章节、列表项或其他文档元素。在本文中,我们将深入探讨 CSS 计数器的使用方法、优势和实际应用场景。 CSS 计数器的基本概念…

基于Sringboot+Vue的校园招聘系统【原创】【开源】

浏览器&#xff1a;Chrome或360浏览器 系统环境配置 前置条件&#xff1a;系统已经安装了Mysql5.7、Mysql工具&#xff08;Navicat&#xff09;、JDK1.8、Maven3.6.1、vue3.0以下开发环境、 Intellij Idea、 Chrome或360浏览器 1、导入数据库 2、编译前端代码vue 编译&…

C++笔记之通过CMakeLists.txt像使用boost库一样使用qt库中特有的模块来方便开发

C++笔记之通过CMakeLists.txt像使用boost库一样使用qt库中特有的模块来方便开发 code review! 文章目录 C++笔记之通过CMakeLists.txt像使用boost库一样使用qt库中特有的模块来方便开发1.文件结构2.CMakeLists.txt3.main.cpp4.运行1.文件结构 . ├── CMakeLists.txt └──…

设计模式--动态代理

动态代理是 Java 中一种常见的设计模式&#xff0c;它允许在运行时创建一个实现一组接口的代理类对象。Java 提供了 java.lang.reflect 包来支持动态代理的实现。在 JDK 中&#xff0c;可以使用 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来创建动…

Hive怎么调整优化Tez引擎的查询?在Tez上优化Hive查询的指南

文章目录 在Tez上优化Hive查询的指南调优指南理解Tez中的并行化理解mapper数量理解reducer数量 并发案例1&#xff1a;未指定队列名称案例2&#xff1a;指定队列名称并发的指南/建议 容器复用和预热容器容器复用预热容器 一般Tez调优参数 在Tez上优化Hive查询的指南 在Tez上优…