前端开发设计模式——状态模式

news2024/10/16 13:05:44

目录

一、状态模式的定义和特点

二、状态模式的结构与原理

1.结构:

2.原理:

三、状态模式的实现方式

四、状态模式的使用场景

1.按钮的不同状态:

2.页面加载状态:

3.用户登录状态:

五、状态模式的优点

1.提高代码的可维护性:

2.增强代码的可读性:

3.更好的处理动态变化:

六、状态模式的缺点

1.增加了代码的复杂性:

2.可能会增加内存占用:

七、状态模式的注意事项

1.状态的划分要合理:

2.状态的转换要清晰:

3.注意性能问题:


一、状态模式的定义和特点

        定义:状态模式允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

        特点:

                将状态的行为封装在独立的状态类中,使得状态的转换更加清晰、可维护。

                减少了条件判断语句,使代码更加简洁、易于理解。

                实现了状态与行为的解耦,使得状态的变化不会影响到对象的其他部分。

二、状态模式的结构与原理

1.结构:

        1.1  状态接口:

                定义了一组方法,这些方法代表了对象在不同状态下的行为。

        1.2  具体状态类:

                实现状态接口,每个具体状态类代表对象的一种特定状态,并实现与该状态相关的行为。

        1.3  上下文对象:

                拥有一个对当前状态的引用,并将与状态相关的操作委托给当前状态对象。当上下文对象的内部状态发生变化时,它会切换到不同的具体状态类,从而改变其行为。

2.原理:

        通过将对象的行为与状态分离,使得对象可以在不同的状态下表现出不同的行为。当对象的状态发生变化时,它会自动切换到相应的状态类,执行该状态下的行为。

三、状态模式的实现方式

步骤:

1.定义状态接口,明确在不同状态下需要实现的方法。

        示例:

class State {
  handleEvent() {
    throw new Error('This method must be overridden.');
  }
}

2.创建具体状态类,实现状态接口,并在每个类中实现特定状态下的行为。

        示例:

class StateA extends State {
  handleEvent() {
    console.log('In State A.');
    // 执行状态 A 下的特定行为
  }
}

class StateB extends State {
  handleEvent() {
    console.log('In State B.');
    // 执行状态 B 下的特定行为
  }
}

3.在上下文对象中,维护一个对当前状态的引用,并提供方法来设置和切换状态。上下文对象将与状态相关的操作委托给当前状态对象执行。

        示例:

class Context {
  constructor() {
    this.state = new StateA();
  }

  setState(state) {
    this.state = state;
  }

  handleEvent() {
    this.state.handleEvent();
  }
}

四、状态模式的使用场景

1.按钮的不同状态:

        例如按钮有正常状态、禁用状态、鼠标悬停状态等,每个状态下的行为不同,可以使用状态模式来管理这些状态和行为。

2.页面加载状态:

        页面在加载数据时可能处于不同的状态,如正在加载、加载成功、加载失败等,可以使用状态模式来处理不同状态下的显示和交互。

        示例:

                假设我们正在开发一个新闻资讯类的网页应用。当用户打开页面时,页面需要从服务器获取新闻数据并展示给用户。在这个过程中,页面会经历不同的状态:

                (1)正在加载状态:页面刚打开时,显示一个加载动画,告知用户数据正在加载中。此时可以创建一个 “加载中” 的状态类,比如:

class LoadingState {
  show() {
    document.getElementById('content').innerHTML = '<div class="loader">Loading...</div>';
  }
}

                (2)加载成功状态:当数据成功从服务器返回并渲染到页面上时,显示新闻列表。创建一个 “加载成功” 的状态类

class SuccessState {
  show(data) {
    let html = '';
    data.forEach(item => {
      html += `<div>${item.title}</div>`;
    });
    document.getElementById('content').innerHTML = html;
  }
}

                (3)加载失败状态:如果数据加载过程中出现错误,显示错误提示信息。对应的状态类如下:

class ErrorState {
  show() {
    document.getElementById('content').innerHTML = '<div class="error">Failed to load data.</div>';
  }
}

                 然后创建一个上下文对象来管理这些状态:

class PageStateContext {
  constructor() {
    this.state = new LoadingState();
  }

  setState(state) {
    this.state = state;
  }

  show() {
    this.state.show();
  }
}

                 在实际使用中,可以根据不同的情况切换状态:

const context = new PageStateContext();
// 模拟数据加载
setTimeout(() => {
  const isSuccess = Math.random() > 0.5;
  if (isSuccess) {
    const data = [
      { title: 'News 1' },
      { title: 'News 2' }
    ];
    context.setState(new SuccessState());
    context.show(data);
  } else {
    context.setState(new ErrorState());
    context.show();
  }
}, 2000);

3.用户登录状态:

        用户在未登录、登录中、已登录等状态下,页面的显示和功能会有所不同,可以使用状态模式来管理这些状态。

        示例:

                在一个社交类的前端应用中,用户的登录状态会影响页面的显示和功能。可以使用状态模式来管理用户的登录状态:

                (1)未登录状态:显示登录按钮和注册链接。状态类如下:

class NotLoggedInState {
  show() {
    document.getElementById('userArea').innerHTML = '<button>Login</button><a href="#">Register</a>';
  }
}

                (2) 登录中状态:显示加载动画,提示用户正在登录。状态类为:
 

class LoggingInState {
  show() {
    document.getElementById('userArea').innerHTML = '<div class="loader">Logging in...</div>';
  }
}

                (3) 已登录状态:显示用户头像和用户名,以及退出登录按钮。状态类如下:

class LoggedInState {
  show(user) {
    document.getElementById('userArea').innerHTML = `<img src="${user.avatar}" alt="Avatar"><span>${user.username}</span><button>Logout</button>`;
  }
}

                 创建上下文对象来管理这些状态:

class UserStateContext {
  constructor() {
    this.state = new NotLoggedInState();
  }

  setState(state) {
    this.state = state;
  }

  show() {
    this.state.show();
  }
}

                 在实际应用中,可以根据用户的操作切换状态:

const context = new UserStateContext();
// 模拟用户点击登录按钮
document.getElementById('loginButton').addEventListener('click', () => {
  context.setState(new LoggingInState());
  context.show();
  // 模拟登录成功
  setTimeout(() => {
    const user = { username: 'John', avatar: 'avatar.jpg' };
    context.setState(new LoggedInState());
    context.show(user);
  }, 2000);
});
// 模拟用户点击退出登录按钮
document.getElementById('logoutButton').addEventListener('click', () => {
  context.setState(new NotLoggedInState());
  context.show();
});

五、状态模式的优点

1.提高代码的可维护性:

        状态和行为的分离使得代码更加清晰,易于修改和扩展。

2.增强代码的可读性:

        通过将状态的行为封装在独立的类中,使得代码的逻辑更加清晰,易于理解。

3.更好的处理动态变化:

        可以轻松地添加新的状态和行为,适应不断变化的需求。

六、状态模式的缺点

1.增加了代码的复杂性:

        引入了更多的类和对象,可能会使代码结构变得更加复杂。

2.可能会增加内存占用:

        每个状态都需要一个具体的状态类实例,可能会占用更多的内存。

七、状态模式的注意事项

1.状态的划分要合理:

        根据实际需求合理划分状态,避免状态过多或过少。

2.状态的转换要清晰:

        确保状态之间的转换逻辑清晰,避免出现混乱的状态转换。

3.注意性能问题:

        如果状态的切换非常频繁,可能会影响性能,可以考虑优化状态的管理方式。

关于状态模式的介绍就到此结束,如果对于其他设计模式感兴趣的话,可以看看下方的专栏目录,里面有其他设计模式的文章。码字不易,点个赞再走吧

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

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

相关文章

vue+element的confirm提示消息文字变色和换行

效果: 思路: 可以考虑采用模板字符串的思路实现 代码: this.confirm(您确定要<b style"Color: red">${text}</b>的数据项&#xff1f;<br/>单位名称: ${row.companyName} <br/>属性: ${row.attributeName}).then(() > {console.log(确定…

一、定时器的时钟来源

计数器的时钟选择8个时钟源&#xff0c;可以分成4类: 一、来自RCC的内部时钟TIMx CLK 二、芯片内部其他定时器的触发输入ITR 使用某一个定时器作为另外一个定时器的分频 ITR1、ITR2、ITR3和ITR4 三、外部时钟源模式1&#xff1a; 外部捕获引脚上的边沿信号 TI1FP…

趋势(一)利用python绘制折线图

趋势&#xff08;一&#xff09;利用python绘制折线图 折线图&#xff08; Line Chart&#xff09;简介 折线图用于在连续间隔或时间跨度上显示定量数值&#xff0c;最常用来显示趋势和关系&#xff08;与其他折线组合起来&#xff09;。折线图既能直观地显示数量随时间的变化…

从零开始在Windows系统上搭建一个node.js后端服务项目

目录 一、下载node.js及配置环境 二、搭建node.js项目及安装express框架 三、集成nodemon&#xff0c;实现代码热部署 四、Express 应用程序生成器 一、下载node.js及配置环境 网上很多安装教程&#xff0c;此处就不再赘述了 版本信息 C:\Users\XXX>node -v v20.15.0…

Go语言基础学习(Go安装配置、基础语法)

一、简介及安装教程 1、为什么学习Go&#xff1f; 简单好记的关键词和语法&#xff1b;更高的效率&#xff1b;生态强大&#xff1b;语法检查严格&#xff0c;安全性高&#xff1b;严格的依赖管理&#xff0c; go mod 命令&#xff1b;强大的编译检查、严格的编码规范和完整的…

微信小程序应用echarts和二维表的结合

1.刚进入页面时&#xff0c;小馋猫图片的位置是由echarts图表的&#xff0c;这个你别管&#xff0c;我有我的难处&#xff0c;是由二维表组成的 当滑动鼠标时&#xff0c;会出现这种情况&#xff0c;echarts图表随着鼠标滑动&#xff0c;位置不固定 3.解决问题&#xff0c;因为…

用manim实现内燃机引擎的活塞,连杆和曲柄的模拟运动【上】

一&#xff0c;介绍 内燃机引擎是现代机械设备中一种非常重要的动力装置&#xff0c;其核心部件包括活塞、连杆和曲柄。活塞在气缸内做往复运动&#xff0c;通过连杆与曲柄相连&#xff0c;将往复运动转化为旋转运动&#xff0c;驱动机械设备正常工作。 活塞是内燃机引擎的关键…

VSCode中的TypeScript教程

TypeScript 是JavaScript的类型化超集&#xff0c;可编译为纯JavaScript。它提供了类、模块和接口来帮助您构建健壮的组件。 安装 TypeScript 编译器 Visual Studio Code 包括 TypeScript 语言支持&#xff0c;但不包括 TypeScript 编译器tsc。您需要在全局或工作区中安装Typ…

【C语言】预编译+编译+汇编+链接

文章目录 翻译环境和运行环境翻译环境预处理&#xff08;预编译&#xff09;编译汇编链接 运行环境 接下来是预处理阶段的一系列知识&#xff0c;认真阅读哦预定义符号#define定义常量#define定义宏带有副作用的宏参数宏替换的规则宏函数的对比#和##命名约定#undef命令行定义条…

C++初阶(五)--类和对象(中)--默认成员函数

目录 一、默认成员函数&#xff08;Default Member Functions&#xff09; 二、构造函数&#xff08; Constructor&#xff09; 1.构造函数的基本概念 2.构造函数的特征 3.构造函数的使用 无参构造函数 和 带参构造函数 注意事项&#xff1a; 4.默认构造函数 隐式生成的…

恢复已删除文件的 10 种安卓数据恢复工具

由于我们现在在智能手机上存储了大量重要文件&#xff0c;因此了解数据恢复工具变得很重要。您永远不会知道什么时候需要使用 安卓 数据恢复工具。 由于不乏 Windows 数据恢复工具&#xff0c;因此从崩溃的计算机中恢复文件很容易。但是&#xff0c;当涉及到从 安卓恢复数据时…

大数据-171 Elasticsearch ES-Head 与 Kibana 配置 使用 测试

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

Go语言Gin框架的常规配置和查询数据返回json示例

文章目录 路由文件分组查询数据库并返回jsonservice层controller路由运行效果 启动多个服务 在 上一篇文章《使用Go语言的gorm框架查询数据库并分页导出到Excel实例》 中主要给大家分享了较多数据的时候如何使用go分页导出多个Excel文件并合并的实现方案&#xff0c;这一篇文章…

unity学习-全局光照(GI)

在全局光照&#xff08;Lighting&#xff09;界面有两个选项 Realtime Light&#xff08;实时光照&#xff09;&#xff1a;在项目中会提前计算好光照以及阴影的程序&#xff0c;当你需要调用实时全局光照的时候会将程序调用出来使用 Mixed Light&#xff08;烘焙光照&#x…

如何利用kafka实现高效数据同步?

在我们之前的文章有详细介绍过Kafka的结构、特点和处理方式。具备告诉处理能力的kafka被利用在数据同步和数据传输上&#xff0c;今天来说下kafka是怎么实现高效的数据同步和传输。 一、可靠的数据传输 1. 持久性保证&#xff1a;Kafka 将数据持久化到磁盘上&#xff0c;即使在…

汽车管理系统——主界面制作

目录 主界面需要有什么&#xff1f;然后要做什么&#xff1f;添加两个主菜单&#xff08;声明&#xff09;下一步应该干什么&#xff1f;能够跳转到文件有哪几个动作&#xff1f;动作如何声明&#xff1f;为什么用选择声明指针&#xff0c;不选择直接声明这个对象&#xff1f; …

算力基础篇:从零开始了解算力

什么是算力 算力即计算能力&#xff08;Computing Power&#xff09;&#xff0c;狭义上指对数字问题的运算能力&#xff0c;而广义上指对输入信息处理后实现结果输出的一种能力。虽然处理的内容不同&#xff0c;但处理过程的能力都可抽象为算力。比如人类大脑、手机以及各类服…

git 与 github 同步

1.配置账户 git config --global user.name "你的用户名" git config --global user.email "你的邮箱" 2.输入命令创建ssh key $ ssh-keygen -t rsa -C "邮箱" //你自己注册GitHub的邮箱 输入命令之后提示输入密码&#xff0c;回车直到出现…

C++类(3)

1.如果一个类什么成员都没有&#xff0c;简称空类 但是空类真的什么都没有吗&#xff1f; 并不是&#xff0c;任何类什么都不写&#xff0c;编译器会自动生成以下6个默认成员函数 1.构造函数 class Date { public:void Init(int year, int month, int day){_year year;_mo…

kubernetes简介及安装部署

目录 一、kubernetes简介 1、k8s的概念 2、k8s各个组件及用途 3、k8s各组件之间的调用关系 4、k8s常用名词概念 5、k8s的分层架构 二、kubernetes安装部署 1、k8s集群环境搭建 2、本地解析、swap禁用 3、安装docker 4、复制harbor仓库中的证书并启动docker 5、设定d…