状态模式-举例

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

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

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

某银行要开发一套信用卡业务系统,银行账户(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.hqwc.cn/news/308700.html

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

相关文章

mongoose中http server服务器解决“Access-Control-Allow-Origin mongoose”跨域问题

问题 使用mongoose做http服务器&#xff0c;自己构造的浏览器端jquery在访问server时&#xff0c;会遇到&#xff1a; Access to XMLHttpRequest at http://127.0.0.1:8000/ from origin null has been blocked by CORS policy: No Access-Control-Allow-Origin header is pr…

rax3000m刷openwrt固件

rax3000m刷机过程&#xff08;nand版本&#xff09; 刷机准备文件https://www.123pan.com/s/X5m9-6Ynj.html提取码:VtBW 接线关系&#xff1a;路由器lan口接电脑 1.上传配置开启ssh的配置文件&#xff08;登录路由器后台管理界面在找到配置管理&#xff0c;上传配置文件rax3…

计算机网络【DNS】

DNS 基本概述 与 HTTP、FTP 和 SMTP 一样&#xff0c;DNS 协议也是应用层的协议&#xff0c;DNS 使用客户-服务器模式运行在通信的端系统之间&#xff0c;在通信的端系统之间通过下面的端到端运输协议来传送 DNS 报文。但是 DNS 不是一个直接和用户打交道的应用。DNS 是为因特…

Nature Machine Intelligence 人形机器人的层次化生成建模

2023年11月2日&#xff0c;德国英特尔研究院&#xff0c;英国伦敦大学学院和美国VERSES研究实验室的研究人员在《Nature Machine Intelligence》杂志发表了一篇题为“Hierarchical generative modelling for autonomous robots”的论文。 研究内容 人类通过规划、执行和…

某后台管理系统加密参数逆向分析

前言 在我们日常的渗透中经常会遇到开局一个登录框的情况&#xff0c;弱口令爆破当然是我们的首选。但是有的网站会对账号密码等登录信息进行加密处理&#xff0c;这一步不由得阻碍了很多人的脚步。前端的加解密是比较常见的&#xff0c;无论是 web 后台还是小程序&#xff0c…

【音视频 ffmpeg 学习】 跑示例程序 持续更新中

环境准备 在上一篇文章 把mux.c 拷贝到main.c 中 使用 attribute(unused) 消除警告 __attribute__(unused)/** Copyright (c) 2003 Fabrice Bellard** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated docu…

Unity JSON编码解码之LitJson 深度剖析

把LitJson的代码库放入到项目中&#xff0c;如图所示:JSON在游戏开发中是一种序列化/反序列化常用的技术&#xff0c;把游戏相关的数据,如地图组成,通过JSON编码&#xff0c;序列化成JSON文本&#xff0c;传输或存储, 要使用的时候再通过JSON技术把文本解析成数据对象&#xff…

Python FastApi连接oracle进行查询

这边技术选型是cx_oracle进行连接查询&#xff0c;cx_oracle的使用首先要有官方的客户端才能连接到数据库&#xff0c;python并不自带客户端。我用是Python3.9 安装客户端 可以到官网在选择最新版进行下载。 Instant Client for Microsoft Windows (x64) 64-bit 或者直接从我…

Cassandra详解

Cassandra 概念 Apache Cassandra 是高度可扩展的&#xff0c;高性能的分布式 NoSQL 数据库。 Cassandra 旨在处理许多商品服务器上的大量数据&#xff0c;提供高可用性而无需担心单点故障。 Cassandra 具有能够处理大量数据的分布式架构。 数据放置在具有多个复制因子的不同…

水准网、平面导线平差

东北大学测绘工程水准网、平面闭合导线间接平差法平差C#项目。 闭合导线程序界面&#xff1a; 水准网程序界面&#xff1a; 项目gitee地址&#xff1a; horizon: 东北大学测绘工程水准网&#xff0c;闭合导线间接平差法C#项目 (gitee.com) 注&#xff1a;此项目为本博主代人转…

C#中使用using关键字回收资源

目录 一、一般表达式 二、示例 三、生成 在进行文件操作后要显式调用文件流的Close方法释放文件资源&#xff0c;在使用数据库连接时也要调用连接对象的Close方法释放数据库资源。如果忘记调用Close方法&#xff0c;有可能会导致程序执行异常&#xff0c;而且还会导制垃圾收…

操作系统大题

目录 作业一&#xff1a; 前驱图 作业二&#xff1a;信号量 作业三&#xff1a;同步算法 1‘’生产者消费者问题 解1&#xff1a; 解2&#xff1a;利用AND信号量解决生产者-消费者问题 解3. 利用管程解决生产者-消费者问题 2‘’ 哲学家进餐问题&#xff08;The Dinning…