状态模式-举例

news2025/1/21 9:23:12

在软件系统中,有些对象也像水一样具有多种状态,
这些状态在某些情况下能够相互转换,
而且对象在不同的状态下也将具有不同的行为。

参考日志来设置状态。
如何判断一个设计模式是行为模式还是什么其他模式?
什么叫行为模式?
行为模式关注对象之间的通讯、职责分配和算法的抽象。它主要解决
的是对象之间的协作问题,确保对象能够协同工作而不紧密耦合。

状态模式:允许一个对象在其内部状态改变时改变它的行为,对象
看起来似乎修改它的类。其别名为状态对象,状态模式是一种
状态行为模式。

某银行要开发一套信用卡业务系统,银行账户(Account)是该系统的核心类之一,通过分析,账户存在三种状态,且在不同状态下账户存在不同的行为,具体说明如下:
 
       (1) 如果账户中余额大于等于0,则账户的状态为正常状态(Normal State),此时用户既可以向该账户存款也可以从该账户取款;
 
       (2) 如果账户中余额小于0,并且大于-2000,则账户的状态为透支状态(Overdraft State),此时用户既可以向该账户存款也可以从该账户取款,但需要按天计算利息;
 
       (3) 如果账户中余额等于-2000,那么账户的状态为受限状态(Restricted State),此时用户只能向该账户存款,不能再从中取款,同时也将按天计算利息;
 
       (4) 根据余额的不同,以上三种状态可发生相互转换。

NormalState表示正常状态,OverdraftState表示透支状态,RestrictedState表示受限状态,在这三种状态下账户对象拥有不同的行为,方法deposit()用于存款,withdraw()用于取款,computeInterest()用于计算利息,stateCheck()用于在每一次执行存款和取款操作后根据余额来判断是否要进行状态转换并实现状态转换,相同的方法在不同的状态中可能会有不同的实现。

客户端代码

我们客户端直接操作一个账户对象,进行取款存款操作。但是随着操作的进行,账户内部一直在进行账户状态的维护。但是客户端没有任何感知,也不需要关心。

package behavioral.state;
 
public class Client {
    public static void main(String args[]) {
        Account acc = new Account("段誉",0.0);
        acc.deposit(1000);
        acc.withdraw(2000);
        acc.deposit(3000);
        acc.withdraw(4000);
        acc.withdraw(1000);
        acc.computeInterest();
    }
}

3)账户类代码

账户类组合了一个AccountState类,用于标识当前账户的状态,同时对账户发起操作请求时,根据不同的账户状态,相应的操作及权限限制也不同。这个根据不同状态做出不同操作的实现原理是多态。

package behavioral.state;
 
//银行账户:环境类
class Account {
    private AccountState state; //维持一个对抽象状态对象的引用
    private String owner; //开户名
    private double balance = 0; //账户余额
 
    public Account(String owner,double init) {
        this.owner = owner;
        this.balance = balance;
        this.state = new NormalState(this); //设置初始状态
        System.out.println(this.owner + "开户,初始金额为" + init);
        System.out.println("---------------------------------------------");
    }
 
    public double getBalance() {
        return this.balance;
    }
 
    public void setBalance(double balance) {
        this.balance = balance;
    }
 
    public void setState(AccountState state) {
        this.state = state;
    }
 
    public void deposit(double amount) {
        System.out.println(this.owner + "存款" + amount);
        state.deposit(amount); //调用状态对象的deposit()方法
        System.out.println("现在余额为"+ this.balance);
        System.out.println("现在帐户状态为"+ this.state.getClass().getSimpleName());
        System.out.println("---------------------------------------------");
    }
 
    public void withdraw(double amount) {
        System.out.println(this.owner + "取款" + amount);
        state.withdraw(amount); //调用状态对象的withdraw()方法
        System.out.println("现在余额为"+ this.balance);
        System.out.println("现在帐户状态为"+ this. state.getClass().getSimpleName());
        System.out.println("---------------------------------------------");
    }
 
    public void computeInterest()
    {
        state.computeInterest(); //调用状态对象的computeInterest()方法
    }
}

账户状态抽象类

 在状态模式中,我们将对象在不同状态下的行为封装到不同的状态类中,为了让系统具有更好的灵活性和可扩展性,同时对各状态下的共有行为进行封装,我们需要对状态进行抽象,引入了抽象状态类角色。 

package behavioral.state;
//抽象状态类
public abstract class AccountState {
    protected Account acc;
    public abstract void deposit(double amount);//存款
    public abstract void withdraw(double amount);//取款
    public abstract void computeInterest();//计算利息
    public abstract void stateCheck();//检查和切换状态
}

正常状态类代码

如果账户中余额大于等于0,则账户的状态为正常状态(Normal State),此时用户既可以向该账户存款也可以从该账户取款

package behavioral.state;
 
public //正常状态:具体状态类
class NormalState extends AccountState {
    public NormalState(Account acc) {
        this.acc = acc;
    }
 
    public NormalState(AccountState state) {
        this.acc = state.acc;
    }
 
    public void deposit(double amount) {
        acc.setBalance(acc.getBalance() + amount);
        stateCheck();
    }
 
    public void withdraw(double amount) {
        acc.setBalance(acc.getBalance() - amount);
        stateCheck();
    }
 
    public void computeInterest()
    {
        System.out.println("正常状态,无须支付利息!");
    }
 
    //状态转换
    public void stateCheck() {
        if (acc.getBalance() > -2000 && acc.getBalance() <= 0) {
            acc.setState(new OverdraftState(this));
        }
        else if (acc.getBalance() == -2000) {
            acc.setState(new RestrictedState(this));
        }
        else if (acc.getBalance() < -2000) {
            System.out.println("操作受限!");
        }
    }
}

透支状态代码

如果账户中余额小于0,并且大于-2000,则账户的状态为透支状态(Overdraft State),此时用户既可以向该账户存款也可以从该账户取款,但需要按天计算利息;

package behavioral.state;
//透支状态:具体状态类
public class OverdraftState extends AccountState
{
    public OverdraftState(AccountState state) {
        this.acc = state.acc;
    }
 
    public void deposit(double amount) {
        acc.setBalance(acc.getBalance() + amount);
        stateCheck();
    }
 
    public void withdraw(double amount) {
        acc.setBalance(acc.getBalance() - amount);
        stateCheck();
    }
 
    public void computeInterest() {
        System.out.println("计算利息!");
    }
 
    //状态转换
    public void stateCheck() {
        if (acc.getBalance() > 0) {
            acc.setState(new NormalState(this));
        }
        else if (acc.getBalance() == -2000) {
            acc.setState(new RestrictedState(this));
        }
        else if (acc.getBalance() < -2000) {
            System.out.println("操作受限!");
        }
    }
}

7)受限状态代码

如果账户中余额等于-2000,那么账户的状态为受限状态(Restricted State),此时用户只能向该账户存款,不能再从中取款,同时也将按天计算利息;

package behavioral.state;
//受限状态:具体状态类
public class RestrictedState extends AccountState {
    public RestrictedState(AccountState state) {
        this.acc = state.acc;
    }
 
    public void deposit(double amount) {
        acc.setBalance(acc.getBalance() + amount);
        stateCheck();
    }
 
    public void withdraw(double amount) {
        System.out.println("帐号受限,取款失败");
    }
 
    public void computeInterest() {
        System.out.println("计算利息!");
    }
 
    //状态转换
    public void stateCheck() {
        if(acc.getBalance() > 0) {
            acc.setState(new NormalState(this));
        }
        else if(acc.getBalance() > -2000) {
            acc.setState(new OverdraftState(this));
        }
    }
}

stateCheck()状态监测类用于监测当前账户金额情况,做出相应的状态切换操作。该方法也可以放在Accout类中。

https://github.com/phs999/DesignPatterns/tree/8ed9fd54d05d7da99833b6fa89e081c21938481b/design_pattern/src/behavioral/state

3、总结
状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化,对于客户端而言,无须关心对象状态的转换以及对象所处的当前状态,无论对于何种状态的对象,客户端都可以一致处理。

核心原理还是面向接口编程,多态。

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

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

相关文章

山西电力市场日前价格预测【2023-12-28】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-12-28&#xff09;山西电力市场全天平均日前电价为814.30元/MWh。其中&#xff0c;最高日前电价为1500.00元/MWh&#xff0c;预计出现在08:00~08:45,17:00~20:15。最低日前电价为394.61元/…

FFmpeg学习笔记--Centos8安装FFmpeg

1--安装指令 sudo yum install epel-releasesudo yum localinstall --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpmsudo yum install ffmpeg ffmpeg-develffmpeg -version 2--版本信息

设计模式-注册模式

设计模式专栏 模式介绍模式特点应用场景注册模式和单例模式的区别代码示例Java实现注册模式Python实现注册模式 注册模式在spring中的应用 模式介绍 注册模式是一种设计模式&#xff0c;也称为注册树或注册器模式。这种模式将类的实例化和创建分离开来&#xff0c;避免在应用程…

Linux文件的扩展属性 attr cap

文件属性 Linux文件属性分为常规属性与扩展属性&#xff0c;其中扩展属性有两种&#xff1a;attr与xattr. 一般常规的文件属性由stat API 读取&#xff0c;一般是三种权限&#xff0c;ower, group&#xff0c;时间等。 扩展属性attr 用户态API ioctl(fd, FS_IOC32_SETFLAGS…

shiro1.10版本后-IniSecurityManagerFactory过期失效

1、问题概述&#xff1f; 今天在研究了shiro的新版本shiro1.13.0版本&#xff0c;发现用了很长时间的IniSecurityManagerFactory工厂失效了。 从下图中可以看出&#xff0c;在新版本中IniSecurityManagerFactory被打上了过期线了。 那么问题来了&#xff0c;新版本如何使用呢…

数据压缩专题——静止图像的小波变换编码

随着数字图像技术的发展和应用的广泛&#xff0c;对图像的压缩和编码变得越来越重要。小波变换编码作为一种有效的图像压缩和编码方法&#xff0c;在静止图像处理中得到了广泛应用。本文将介绍静止图像的小波变换编码的基本原理和关键步骤&#xff0c;以及其在图像压缩中的应用…

1panel使用指南(一)面板安装

一、1panel简介 1Panel是杭州飞致云信息科技有限公司推出的产品 [1]&#xff0c;帮助用户实现快速建站。 [2]是一款现代化、开源的Linux服务器运维管理面板&#xff0c;于2023年3月推出&#xff0c;深度集成WordPress和Halo&#xff0c;一键完成域名绑定、SSL证书配置等操作&a…

用linux中定时任务Crontab,向企业微信群通过机器人发送消息

1.使用yum命令安装Crontab&#xff1a;这个很关键&#xff0c;没有安装的话会提示命令not found yum install vixie-cron yum install crontabs 注&#xff1a;vixie-cron软件包是cron的主程序&#xff1b; crontabs软件包是用来安装、卸装、或列举用来驱动 cron 守护进程的表…

Hadoop(2):常见的MapReduce[在Ubuntu中运行!]

1 以词频统计为例子介绍 mapreduce怎么写出来的 弄清楚MapReduce的各个过程&#xff1a; 将文件输入后&#xff0c;返回的<k1,v1>代表的含义是&#xff1a;k1表示偏移量&#xff0c;即v1的第一个字母在文件中的索引&#xff08;从0开始数的&#xff09;&#xff1b;v1表…

C#中使用is关键字检查对象是否与给定类型兼容

目录 一、定义 二、示例 三、生成 在程序的开发过程中经常会使用类型转换&#xff0c;如果类型转换不成功则会出现异常&#xff0c;从抛出异常到捕获并处理异常&#xff0c;无形中增加了系统的开销&#xff0c;而且太过频繁地处理异常还会严重地影响系统的稳定性。is关键字可…

要学习openfoam,c++需要掌握到什么程度?

要学习openfoam&#xff0c;c需要掌握到什么程度&#xff1f; 在开始前我有一些资料&#xff0c;是我根据自己从业十年经验&#xff0c;熬夜搞了几个通宵&#xff0c;精心整理了一份「c的资料从专业入门到高级教程工具包」&#xff0c;点个关注&#xff0c;全部无偿共享给大家&…

JY901S 9轴姿态角度传感器模块

JY901S 9轴姿态角度传感器模块 JY901S 简介模块特性引脚说明IIC通讯IIC读写寄存器代码示例 JY901S 简介 模块集成高精度的陀螺仪、加速度计、地磁场传感器&#xff0c;采用高性能的微处理器和先进的动力学解算与卡尔曼动态滤波算法&#xff0c;能够快速求解出模块当前的实时运…

PHP序列化总结2--常见的魔术方法

魔术方法的概念 PHP的魔术方法是一种特殊的方法&#xff0c;用于覆盖PHP的默认操作。它们以双下划线&#xff08;__&#xff09;开头&#xff0c;后面跟着一些特定的字符串&#xff0c;如__construct()、__destruct()、__get()等。这些魔术方法在对象执行特定操作时被自动调用…

OpenCV-Python(22):直方图的计算绘制与分析

目标 了解直方图的原理及应用使用OpenCV 或Numpy 函数计算直方图使用Opencv 或者Matplotlib 函数绘制直方图学习函数cv2.calcHist()、np.histogram()等 原理及应用 直方图是一种统计图形&#xff0c;是对图像的另一种解释&#xff0c;用于表示图像中各个像素值的频次分布。直…

【Linux Shell学习笔记】Linux Shell的位置参数与函数

一、位置参数 位置参数&#xff0c;也被称之为位置变量&#xff0c;通过位置参数&#xff0c;可以在执行程序的时候&#xff0c;向程序传递数据 1.1 shell接收参数的方法 1.2 向shell传递参数的方法 二、函数 2.1 函数基础 2.1.1 函数简介 函数本质上就是一个代码块&#xf…

【并行计算】GPU,CUDA

一、CUDA层次结构 1.kernel核函数 一个CUDA程序是一个kernel核函数被GPU的多个计算单元并行执行的过程&#xff0c;CUDA给了如下抽象 dim3 threadsPerBlock(4, 3, 1); dim3 numBlocks(3, 2, 1); matrixAdd<<<numBlocks, threadsPerBlock>>>(A, B, C); 2.G…

人工智能的第一性原理

今天跟大家分享一篇 北师大 - 图像处理研究中心主任 郭平教授的一篇文章 通过“四个问题”&#xff0c; 解释了人工智能的第一性原理 提出了如何运用第一性原理思维 来解决人工智能缺乏基本常识的问题 并且他建议将最小作用量原理 作为人工智能的第一性原理 什么是第一…

JavaScript系列——正则表达式

文章目录 需求场景正则表达式的定义创建正则表达式通过 / 表示式/ 创建通过构造函数创建 编写一个正则表达式的模式使用简单模式使用特殊字符常用特殊字符列表特殊字符组和范围 正则表达式使用代码演示 常用示例验证手机号码合法性 小结 需求场景 在前端开发领域&#xff0c;在…

Java注解学习,一文掌握@Autowired 和 @Resource 注解区别

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

【AI导师】利用Coding Agent完成AIGC编程

利用Coding Agent完成AIGC编程 一、前言二、Coding Agent三、1024code四、AI导师README项目初版功能定义代码结构设计方案函数方法设计方案迭代记录 一、前言 AI产品的发展确实在过去两年年中取得了显著进展&#xff0c;尤其是在编程领域。一开始&#xff0c;ChatGPT和类似的语…