常用设计模式系列(十九)- 状态模式
第一节
前言
各位好,随着AI的普及,现在行业越来越不景气了,小编以后要捂紧钱袋子,开源节流,以后超过五块钱的活动都不能参加了,因为没钱!!!
过年期间小编也是生了一场病,吃了好久的药才康复,深刻的认识到了身体免疫力的重要性,所以以后各位也要工作和生活结合,运动+学习+工作+娱乐才是正道,不要把身体搞坏。近期小编也是每天五公里跑步为了减肥+提高免疫力,跑了半个月发现,从小腿疼转移到了半月板疼(膝盖内侧)才瘦了不到三斤,跟朋友聊起来,朋友的一句话让小编体会到了减肥的痛苦:节食减肥吧怕把肠胃搞坏了,运动减肥吧,又怕把半月板搞废了,真的是贼难。。。。。
今天小编拖着自己负债累累+伤痕累累的身体,给大家讲解新的设计模式,设计模式专题也很快就要结束了,小编也抓紧时间讲完给大家分享更多新的知识。今天讲解行为型设计模式中的状态模式。状态模式同样可以使用见形思意的方法,所谓状态,我们在开发某个模块的过程中,也会为数据配置状态字段,例如我们在淘宝上购物,你的订单是待支付状态、已支付待配送的状态等等,根据不同的状态来控制不同的行为,当一个系统中拥有多种数据模型,每个模型有多个状态时,状态间转化时,将其本身原有的行为进行修改的过程,就是状态模式的实现过程。
第二节
状态模式
概念:
状态模式(State Parttern):
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。它用于解决系统中复杂对象的状态转换以及不同状态下行为封装的问题。系统中某个对象存在多个状态,这些状态之间可以进行转换,并且对象在不同状态下行为不相同时可以使用状态模式。
小编生病前,可以随便吃自己喜欢吃的东西,辣的、油腻的,这是一个“正常”的状态,当小编的状态变为“生病”时,小编就限制自己不能吃辣椒、油腻的东西,看起来小编像换了一个人,无辣不欢的人竟然不吃辣椒了,其实小编只是改变(限制)了自己的行为。这就是状态模式。
状态模式及构成
UML图
第三节
场景分析与代码实现
场景举例:
某银行计划研发一批带有储蓄功能的信用卡,既可以进行取款,又可以进行存款,也可以透支消费。故设置了如下几种状态:
1.账户余额大于0,正常状态,可以完成取款、存款、消费操作
2.账户月小于0,但是大于信用额度(默认按照5000计算),只允许进行消费、存款操作
3.账户金额欠费大于5000,则为受限,可以存款,但是不能取款和消费
4.余额的不同可以完成以上三种状态的转换
场景分析:
UML类图
代码实现
1.编写环境类,账户Account
package com.yang.state;
/**
* @ClassName Account
* @Description 账户类
* @Author IT小白架构师之路
* @Date 2021/3/22
* @Version 1.0
**/
public class Account {
public Account(String name,double balance){
this.name = name;
this.balance = balance;
this.state = new NomalState(this);
}
/**
* 账户名
*/
private String name;
private double balance = 0; //余额初始化为0
private State state;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
/**
* 取款
* @param price
*/
public void getMoney(double price){
state.getMoney(price);
}
/**
* 存款
* @param price
*/
public void saveMoney(double price){
state.saveMoney(price);
}
/**
* 消费
* @param price
*/
public void shopping(double price){
state.shopping(price);
}
}
2.编写抽象状态State
package com.yang.state;
/**
* @ClassName State
* @Description 状态类
* @Author IT小白架构师之路
* @Date 2021/3/22
* @Version 1.0
**/
public abstract class State {
protected Account account;
/**
* 取款
* @param price
*/
public abstract void getMoney(double price);
/**
* 存款
* @param price
*/
public abstract void saveMoney(double price);
/**
* 消费
* @param price
*/
public abstract void shopping(double price);
/**
* 转换
*
*/
public void stateCheck() {
//获取金额
double balance = account.getBalance();
if(balance>0){
account.setState(new NomalState(account));
}else if(balance < 0 && balance > -5000){
account.setState(new OverState(account));
}else{
account.setState(new LimitState(account));
}
}
}
3.编写具体状态NomalState
package com.yang.state;
/**
* @ClassName NomalState
* @Description 正常状态
* @Author IT小白架构师之路
* @Date 2021/3/22
* @Version 1.0
**/
public class NomalState extends State{
public NomalState(Account account){
this.account = account;
}
/**
* 取钱
* @param price
*/
public void getMoney(double price) {
double balance = account.getBalance();
balance = balance - price;
account.setBalance(balance);
System.out.println("取款"+price+"成功,余额为"+balance);
stateCheck();
}
/**
* 存钱
* @param price
*/
public void saveMoney(double price) {
double balance = account.getBalance();
balance = balance + price;
account.setBalance(balance);
System.out.println("存款"+price+"成功,余额为"+balance);
stateCheck();
}
/**
* 消费
* @param price
*/
public void shopping(double price) {
double balance = account.getBalance();
balance = balance - price;
account.setBalance(balance);
System.out.println("消费"+price+"成功,余额为"+balance);
stateCheck();
}
}
4.编写具体状态OverState
package com.yang.state;
/**
* @ClassName OverState
* @Description 透支状态
* @Author IT小白架构师之路
* @Date 2021/3/22
* @Version 1.0
**/
public class OverState extends State{
public OverState(Account account){
this.account = account;
}
/**
* 取钱
* @param price
*/
public void getMoney(double price) {
System.out.println("取款失败,透支状态不能取款");
stateCheck();
}
/**
* 存钱
* @param price
*/
public void saveMoney(double price) {
double balance = account.getBalance();
balance = balance + price;
account.setBalance(balance);
System.out.println("存款"+price+"成功,余额为" + balance);
stateCheck();
}
/**
* 消费
* @param price
*/
public void shopping(double price) {
double balance = account.getBalance();
balance = balance - price;
account.setBalance(balance);
System.out.println("消费"+price+"成功,余额为"+balance);
stateCheck();
}
}
5.编写具体状态LimitState
package com.yang.state;
/**
* @ClassName LimitState
* @Description 受限状态
* @Author IT小白架构师之路
* @Date 2021/3/22
* @Version 1.0
**/
public class LimitState extends State{
public LimitState(Account account){
this.account = account;
}
/**
* 取钱
* @param price
*/
public void getMoney(double price) {
System.out.println("受限状态不能取款");
stateCheck();
}
/**
* 存钱
* @param price
*/
public void saveMoney(double price) {
double balance = account.getBalance();
balance = balance + price;
account.setBalance(balance);
System.out.println("存款成功,当前金额为"+balance);
stateCheck();
}
/**
* 消费
* @param price
*/
public void shopping(double price) {
System.out.println("受限状态不能消费");
stateCheck();
}
}
6.编写客户端测试取款、消费
package com.yang.state;
/**
* @ClassName Client
* @Description 客户端测试
* @Author IT小白架构师之路
* @Date 2021/3/22
* @Version 1.0
**/
public class Client {
public static void main(String[] args) {
//开户并存了500
Account account = new Account("IT小白架构师之路",500);
System.out.println("当前账户余额"+account.getBalance());
System.out.println("您当前的账户状态为:" + account.getState().getClass().getName());
//取款600
account.getMoney(600);
System.out.println("您当前的账户状态为:" + account.getState().getClass().getName());
//取款500
account.getMoney(500);
System.out.println("您当前的账户状态为:" + account.getState().getClass().getName());
//消费500
account.shopping(500);
System.out.println("您当前的账户状态为:" + account.getState().getClass().getName());
//消费5000
account.shopping(5000);
System.out.println("您当前的账户状态为:" + account.getState().getClass().getName());
//消费100
account.shopping(100);
}
}
7.测试结果如下,最终程序实现了用户消费及消费取款等操作之间的状态转换,每种状态的行为可以做出限制,实现了状态模式
当前账户余额500.0
您当前的账户状态为:com.yang.state.NomalState
取款600.0成功,余额为-100.0
您当前的账户状态为:com.yang.state.OverState
取款失败,透支状态不能取款
您当前的账户状态为:com.yang.state.OverState
消费500.0成功,余额为-600.0
您当前的账户状态为:com.yang.state.OverState
消费5000.0成功,余额为-5600.0
您当前的账户状态为:com.yang.state.LimitState
受限状态不能消费
第四节
优缺点及适用场景
优点:
1.状态模式封装了状态的转换规则,使用公用的状态转换方式,可以更好地统一管理状态转换规则。
2.状态模式将与某个状态相关的行为放到状态类中,程序只需更换状态便可拥有不同的行为。
3.状态模式的出现可以更便捷的扩展新的状态及行为,并不影响环境本体。
缺点:
适用场景:
1.适用于当系统中某个模块状态之间区分较大时,可以通过状态模式控制其行为。
2.当系统中某个模块在多处对状态进行判断及转换时,可抽象出抽象状态,提炼公用方法,增加代码简介度及减少冗余。
3.程序设计模块需要灵活增加状态来区分行为时,可以使用状态模式。
觉得不错的话,点个关注再走吧