行为型模式 04 状态模式

状态模式State

状态切换
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类
当控制一个对象状态转换的条件表达式过于复杂时的情况,把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化
把各种判断逻辑分布到State的子类之间,来减少相互间的依赖
在这里插入图片描述
Context:环境类,持有对State的引用,实际上拥有状态的对象。
State:抽象状态类,封装与Contex的一个特定状态的行为
ConcreteState 每个类实现了状态具体行为

把各种状态及实现封装成一个ConcreteState,通过Context来操作他们之间的自动状态跳转

切换方式:
1.环境类同时是状态管理器(State Manager),负责状态之间的切换。在环境类的changeState方法中对某些属性做出判断,从而做出相应的转换
2.具体状态类负责状态转换,判断放在其内部

使用场景

某个类的核心状态是易变的,当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时

当控制一个对象状态转换的条件表达式过于复杂时的情况,,把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化

条件表达式一定要是“开关切换状态”,才可以使用State模式,即是根据自身当前状态,会做出不同的行为,这些状态还会在不同的条件下相互转换
开关切换状态:状态本身做为一个判断条件

public class DiffTest {
    public static void main(String[] args) {
        Light light = new Light();
        light.state = "开";
        // 状态模式 开关切换状态,自身参与到条件判断中
        if( light.state.equals("开")){
            light.state = "关";
        }else if (light.state.equals("关")){
            light.state = "开";
        }
        // 策略模式 一般状态判断
        String OtherConditions = "天黑";
        if ( OtherConditions.equals("天黑")){
            light.state = "开";
        }else if (OtherConditions.equals("天亮") ){
            light.state = "关";
        }
    }
}
class Light{
    public String state;
}

与策略模式的区别:
在状态模式中,状态的变迁是由对象的内部条件决定,外界只需关心其接口,不必关心其状态对象的创建和转化;而策略模式里,采取何种策略由外部条件决定。

策略模式的各种策略(具体实现类)是平级的,比如早饭我可以选择吃粥或油条或鸡蛋,我能选择我要吃什么
状态模式的各种状态却不是平级的,而是具有某种转化关系的,即状态迁移,比如水在0度以下会结冰,过了零度会升温.

状态转换场景中,最好不要由客户端来直接改变状态(也不是绝对不可以),而是客户端做了某种其它操作引起状态迁移,也就是说客户端最好不要直接创建一个具体 State 实现类的实例对象,通过 setState() 方法来设置。状态转化也可能是其内部的某些行为造成的

从代码上理解差异:是谁促使了行为的改变

状态模式中,状态转移由 Context 或 State 自己管理。如果你在State中管理状态转移,那么它必须持有Context的引用,在State内部使用Context.SetState()
而策略模式中,Strategy 从不持有Context的引用,是客户端把所选择的 Strategy 传递给Context。
这篇文章讲的很好

实例

银行余额,大于0正常使用,小于0大于-2000限制使用,低于-2000禁止使用

以下实现由ConcreteState管理状态迁移
在这里插入图片描述
State:
账户状态:

public interface AccountState {
    void ShowMoney(AccountContext ac);
}

ConcreteState:
正常下状态,低于0时自动转入下一状态

public class NormalState implements AccountState {

    @Override
    public void ShowMoney(AccountContext accountContext) {
        if (accountContext.getMoney()>0){
            System.out.println("正常使用");
        }
        else {
            accountContext.setState(new LimitState());
            accountContext.show();
        }
    }
}

限制状态:
低于-2000自动转入下一状态

public class LimitState implements AccountState {
    @Override
    public void ShowMoney(AccountContext accountContext) {
        if (accountContext.getMoney()>-2000){
            System.out.println("限制使用");
        }
        else{
            accountContext.setState(new BanState());
            accountContext.show();
        }
    }
}

禁止状态
当前最后的状态,无需再向下进行状态迁移了

public class BanState implements AccountState {
    @Override
    public void ShowMoney(AccountContext accountContext) {

        System.out.println("拒绝使用");
    }
}

Context环境类:

public class AccountContext {
    private double money;
    private AccountState state;
    public AccountContext(){
        state = new NormalState();
    }
    public void setMoney(double money) {
        this.money = money;
    }

    public double getMoney() {
        return money;
    }

    public void setState(AccountState state) {
        this.state = state;
    }
    public void show(){
        state.ShowMoney(this);
    }
}

测试:

public class Test {
    public static void main(String[] args) {
        AccountContext ac = new AccountContext();
        ac.setMoney(-3000);
        ac.show();
    }
}

输出:拒绝使用

根据设置的金额,状态从由正常->限制->禁止,自动转化,最后调用禁止的showmoney

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值