大话设计模式学习笔记(16)——状态模式

源码git地址 https://github.com/dlovetco/designMode

问题提出

人一生有很多个时期,而不同的时期应该做不同的事情。比如童年需要开心的玩耍,青年需要认真工作,老年可以享受天伦之乐。。。用代码实现上述场景。

使用switch实现
package statemode;

public class StateMode {
    public static void main(String[] args) {
        Life life = new Life();
        life.setPeriod("童年");
        life.doThings();
        life.setPeriod("青年");
        life.doThings();
        life.setPeriod("老年");
        life.doThings();
    }
}

class Life {
    public String getPeriod() {
        return period;
    }

    public void setPeriod(String period) {
        this.period = period;
    }

    private String period;//不同的时期

    public void doThings() {
        switch (period) {
            case "童年":
                System.out.println("玩耍");
                break;
            case "青年":
                System.out.println("工作");
                break;
            case "老年":
                System.out.println("享受天伦之乐");
                break;
        }
    }
}

虽然说我们确实已经实现题目要求的场景了,但是大家也能看出很多的问题在其中。
1. 若题目中给的状态很多,那么doThings()方法的switch判断会变得很长(如果使用if-else则会更加长)
2. 如果要新增状态,则需要修改原来的方法。违背了开放封闭原则

根据我们一贯的方式,往往都是增加类的结构层次来把switch逻辑拆开来。于是有了下面的状态模式

状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类
package statemode;

public class StateMode {
    public static void main(String[] args) {
        Life life = new Life();
        life.setPeriod("青年");
        life.doThings();
    }
}

interface State {
    void doThings(Life life);
}

class Life {
    private String period;

    private State state = new Childhood();//初始化是童年

    public void doThings() {
        state.doThings(this);
    }

    public String getPeriod() {
        return period;
    }

    public void setPeriod(String period) {
        this.period = period;
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }
}

class Childhood implements State {

    @Override
    public void doThings(Life life) {
        //是童年就玩耍 否则自动转入青年
        if ("童年".equals(life.getPeriod())) {
            System.out.println("玩耍");
        } else {
            life.setPeriod("青年");
            life.setState(new Youth());
            life.doThings();
        }
    }
}

class Youth implements State {

    @Override
    public void doThings(Life life) {
        if ("青年".equals(life.getPeriod())) {
            System.out.println("工作");
        } else {
            life.setPeriod("老年");
            life.setState(new Elder());
            life.doThings();
        }
    }
}

class Elder implements State {

    @Override
    public void doThings(Life life) {
        if ("老年".equals(life.getPeriod())) {
            System.out.println("享受天伦之乐");
        }
    }
}

输出: 工作
这里先定义了一个State接口,用于表示每个时期要做什么事情。而具体是什么时期,需要另外一个Life类传入参数。童年,青年,老年三个时期分别实现State接口,实现自己不同的doThings()方法。Life类中保存了State的引用和一个period字段表示当前是什么时期。而在Life中的doThings()方法则使用代理的思想,调用State的doThings()方法,这样子的话客户端就不需要知道State的存在,只需要跟Life打交道。此外还有一点,在State的诸多实现类中,如Childhood。它在判断Life传进来的period字段的时候,如果不符合则会自动改变life的状态到青年,再一次调用life.doThings()。由于代理的机制,相当于再一次调用Youth的doThings()。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。状态模式通过把各种状态转移逻辑分不到State的子类中间,减少了相互之间的依赖

plantuml

@startuml
interface State{
{abstract}doThings(Life life)
}
State <|.. Childhood
class Childhood{
doThings(Life life)
}
State <|.. Youth
class Youth{
doThings(Life life)
}
State <|.. Elder
class Elder{
doThings(Life life)
}

State <..* Life
class Life{
String period
State state
}
@enduml

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
状态模式是一种行为型设计模式,它允许对象在内部状态改变时改变它的行为。在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的context对象。 在C++中实现状态模式,可以按照以下步骤进行: 1. 创建一个抽象状态类,其中包含一个纯虚函数,该函数将在具体状态类中实现。 2. 创建具体状态类,这些类继承自抽象状态类,并实现其纯虚函数。 3. 创建context类,该类包含一个指向抽象状态类的指针,并在其内部维护状态。 4. 在context类中实现一些操作,这些操作将根据当前状态调用不同的具体状态类中的方法。 下面是一个简单的示例代码,演示了如何在C++中实现状态模式: ```cpp #include <iostream> using namespace std; // 抽象状态类 class State { public: virtual void handle() = 0; }; // 具体状态类A class ConcreteStateA : public State { public: void handle() { cout << "State A handled." << endl; } }; // 具体状态类B class ConcreteStateB : public State { public: void handle() { cout << "State B handled." << endl; } }; // context类 class Context { private: State* state; public: Context(State* s) { state = s; } void setState(State* s) { state = s; } void request() { state->handle(); } }; // 示例代码 int main() { State* stateA = new ConcreteStateA(); State* stateB = new ConcreteStateB(); Context* context = new Context(stateA); context->request(); // 输出:State A handled. context->setState(stateB); context->request(); // 输出:State B handled. return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值