设计模式(二十一)—— 状态模式(定义、案例分析、特点、缺点)


前言

文章内容主要参考了刘伟主编的《设计模式(第2版)》,同时也结合了自己的一些思考和理解,希望能帮到大家。


本篇讲解状态模式。

在一些情况当中,我们的一个环境可能会有多个状态进行切换,同时,如果单纯的通过当前的状态而在一些方法中大量的使用ifelse语句就会显得非常的冗余,耦合度高,所以便有了状态模式。

正文

一、定义

状态模式(State Pattern) :允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。

对于一个对象的多状态情况,以往的我们会用ifelse解决,但是在添加新的状态时,我们又要修改大量的代码。而我们其实注意到,1.一个对象是有多个不同的状态,它们需要不时的切换。2.当前状态决定当前允许有什么样的行为,而行为过后又有可能需要切换状态
所以针对于此,状态模式的思考方式便是要把不同的状态单独分离出来,同时对于状态下的行为也一同封装在状态下。

其实状态模式有两个难点一个是理解行为怎么样在各状态下不同,第二个就是状态怎么切换的问题。
首先第一个,在我们过往认知中,行为是归属于对象的,所以对象有什么行为我们都是在这个对象中进行实现。而在状态模式中,对象的行为也依旧定义在自己身上,但是具体实现是调用具体状态类的方法,所以其实,行为是重心落在了各个状态中,我们是把状态和行为绑定在一起了,因为他们经常性的互相影响(不同状态决定不同行为,行为可能会切换不同状态)。对象类相当于一个空壳类。
第二个,每个对象中必然有个属性指向特定状态,在需要切换时,可以在行为调用后返回要切换的状态(不切换就return自身),又或者在需要切换时,通过双向关联修改对象的状态。具体看后面的实现可能会明白一些。

二、情景假设

在某银行系统定义的账户有三种状态:
(1) 如果账户(Account)中余额(balance)大于等于0,此时账户的状态为绿色(GreenState),即正常状态,表示既可以向该账户存款(deposit)也可以从该账户取款(withdraw);
(2) 如果账户中余额小于0,并且大于等于-1000,则账户的状态为黄色(YellowState),即欠费状态,此时既可以向该账户存款也可以从该账户取款;
(3) 如果账户中余额小于-1000,那么账户的状态为红色(RedState),即透支状态,此时用户只能向该账户存款,不能再从中取款。
现用状态模式来实现状态的转化问题,用户只需要执行简单的存款和取款操作,系统根据余额数量自动转换到相应的状态。

三、情景分析

关于上面情景的类图(具体分析在下面)
在这里插入图片描述

左边account类相当于定义了一个躯壳并且和一些属性。右边都是状态类,并且行为具体实现在各个状态类中发生。
最后为解决切换问题利用了双向关联。

环境类Account(注意看我注释的那一行)

public class Account {
   
    private AccountState state;
    private String owner;
    public Account(String owner, double init){
   
        this.owner = owner;
        System.out.println(this.owner + "开户,初始账户为" + init);
        System.out.println("----------------------");
        this.state = new GreenState(init, this);//这里注意是把自身传进去,方便状态类使用其中的属性。
    }
    public void setState(AccountState state){
   
        this.state = state;
    }
    public void deposit(double amount){
   
        state.deposit(amount);
    }
    public String getOwner(){
   
        return this.owner;
    }
    public void withdraw(double amount){
   
        state.withdraw(amount);
    }
}

抽象状态类AccountState

 public abstract class AccountState {
   
    protected Account acc;
    protected double balance;
    public abstract void stateCheck();
    public void deposit(double amount){
   
        System.out.println(acc.getOwner() + "存款" + amount);
        this.balance += amount;
        System.out.println("现在余额为" &
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我从四个方面来阐述状态模式。 1. 模式特点定义状态模式是一种行为型设计模式,它允许对象在其内部状态改变时改变它的行为。状态模式通过将状态封装成独立的类,使得状态的变化不会影响到客户端的使用。状态模式状态和行为分离,让状态的变化不影响对象的行为,从而降低了对象间的耦合性。 2. 模式应用场景: 状态模式适用于当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时。状态模式常用于游戏开发、电子商务等领域。 3. 模式案例及代码分析: 以游戏开发为例,假设有一个游戏中的角色,它有三种状态:正常状态、受伤状态和死亡状态。当角色受到攻击时,状态会从正常状态变为受伤状态,当角色生命值为0时,状态会从受伤状态变为死亡状态。我们可以使用状态模式来实现这个场景。 首先,我们定义一个状态接口 State,它有两个方法:doAction() 和 toString()。 ```java public interface State { void doAction(Context context); String toString(); } ``` 然后,我们定义三个状态类:NormalState、InjuredState 和 DeadState。 ```java public class NormalState implements State { public void doAction(Context context) { System.out.println("角色处于正常状态"); context.setState(this); } public String toString() { return "正常状态"; } } public class InjuredState implements State { public void doAction(Context context) { System.out.println("角色处于受伤状态"); context.setState(this); } public String toString() { return "受伤状态"; } } public class DeadState implements State { public void doAction(Context context) { System.out.println("角色已死亡"); context.setState(this); } public String toString() { return "死亡状态"; } } ``` 最后,我们定义一个 Context 类来管理角色的状态。 ```java public class Context { private State state; public Context() { state = new NormalState(); } public void setState(State state) { this.state = state; } public State getState() { return state; } } ``` 当角色受到攻击时,我们可以调用 Context 的 setState() 方法来改变角色的状态。 ```java Context context = new Context(); context.getState().doAction(context); context.setState(new InjuredState()); context.getState().doAction(context); context.setState(new DeadState()); context.getState().doAction(context); ``` 输出结果为: ``` 角色处于正常状态 角色处于受伤状态 角色已死亡 ``` 4. 模式缺点状态模式的优点是可以将对象的状态和行为分离,使得状态的变化不会影响到客户端的使用,同时也降低了对象间的耦合性。状态模式缺点是会增加系统的复杂度,因为它需要引入新的类和接口。另外,如果状态转换比较复杂,可能会导致状态类的数量增加,使得代码结构更加复杂。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值