8. 状态模式

目录

一、应用背景

  • 某对象发生变化时,其所能做的操作也随之变化。
  • 应用程序的可维护性和重用性差
  • 代码的逻辑较复杂

二、状态模式

2.1 解决的问题

  • 允许一个对象在其内部状态改变时改变化的行为

2.2 角色

  • 环境类(Context):客户使用的对象料。维护一个State子类的实例,这个实例定义当前状态
  • 抽象状态类(State):定义一个抽象以封装瑟Context的一个特定状态相关的行为
  • 具体状态类(ConcreteState):每一子类实现一个与Context的一个状态相关的行为

2.3 实现步骤

  • 定义抽象状态类,实现当前系统的真实状态继承自此抽象状态类
  • 定义Context类,具有状态的类,其中包含抽象状态类的对象
  • 定义具体状态类,实现当前系统的真实状态类
    • 当Context类执行某个接口的方法时,去调用真实状态类的实现方法
    • 当Context类修改状态时,修改Context类的真实状态对象

三、通用设计类图

  • Context:上下文/环境类,即状态的拥有者
  • State:抽取出的抽象状态类,里面规定了该类拥有的行
  • Concrete StateA:具体的状态类

四、实现

  • 设置酒店房间管理功能

4.1 设计类图

  • 房间类:环境类,状态拥有者
  • 房间状态类:抽象类,定义房间的状态信息
  • xxx状态类:各种不同的房间状态信息,继承自房间状态类

4.2 状态转换图

4.3 代码实现

cpp 复制代码
#include <iostream>

class Room;

class State
{
public:
    virtual std::string getState() = 0;
    virtual void book(Room* room) = 0;
    virtual void checkin(Room* room) = 0;
    virtual void unbook(Room* room) = 0;
    virtual void checkout(Room* room) = 0;
};

class Room
{
protected:
    State* s;

public:
    std::string getState()
    {
        return s->getState();
    }

    void setState(State* a)
    {
        s = a;
    }

    void book()
    {
        s->book(this);
    }

    void checkin()
    {
        s->checkin(this);
    }

    void unbook()
    {
        s->unbook(this);
    }

    void checkout()
    {
        s->checkout(this);
    }
};

class FreeState : public State
{
public:
    std::string getState() override
    {
        return "当前为空闲状态";
    }

    void book(Room* room) override;

    void checkin(Room* room) override;

    void unbook(Room* room) override
    {
        std::cout << "当前为空闲状态,无法进行取消预定操作" << std::endl;
    }

    void checkout(Room* room) override
    {
        std::cout << "当前为空闲状态,无法进行退房操作" << std::endl;
    }
};

class BookState : public State
{
public:
    std::string getState() override
    {
        return "当前为预定状态";
    }

    void book(Room* room) override
    {
        std::cout << "当前已经是预定状态,无须重复预订" << std::endl;
    }

    void checkin(Room* room) override;

    void unbook(Room* room) override;

    void checkout(Room* room) override
    {
        std::cout << "当前是预定状态,无须退房" << std::endl;
    }
};

class CheckinState : public State
{
public:
    std::string getState() override
    {
        return "当前为入住状态";
    }

    void book(Room* room) override
    {
        std::cout << "当前是入住状态,无法预定" << std::endl;
    }

    void checkin(Room* room) override
    {
        std::cout << "当前是入住状态,无须重复入住" << std::endl;
    }

    void unbook(Room* room) override
    {
        std::cout << "当前是入住状态,无法取消预定" << std::endl;
    }

    void checkout(Room* room) override
    {
        std::cout << "退房操作" << std::endl;
        room->setState(new FreeState());
    }
};

void FreeState::book(Room* room)
{
    std::cout << "预订操作" << std::endl;
    room->setState(new BookState());
}

void FreeState::checkin(Room* room)
{
    std::cout << "入住操作" << std::endl;
    room->setState(new CheckinState());
}

void BookState::checkin(Room* room)
{
    std::cout << "入住操作" << std::endl;
    room->setState(new CheckinState());
}

void BookState::unbook(Room* room)
{
    std::cout << "取消预订操作" << std::endl;
    room->setState(new FreeState());
}

int main()
{
    Room* r = new Room();
    State* s = new FreeState();
    r->setState(s);

    std::cout << "=============================" << std::endl;
    std::cout << r->getState() << std::endl;

    std::cout << "=============================" << std::endl;
    r->checkin();
    std::cout << r->getState() << std::endl;

    std::cout << "=============================" << std::endl;
    r->checkout();
    r->book();
    r->checkout();
    std::cout << r->getState() << std::endl;

    return 0;
}
相关推荐
Zane19943 天前
一个 new 就能创建对象,为什么还要拆出单例、工厂、建造者、原型四种模式?
设计模式
怕浪猫4 天前
一行命令复刻爆款视频,我把 Hypit 从安装跑到了出片
人工智能·设计模式·程序员
Zane19944 天前
函数式编程里的函数,其实不是你天天写的那个函数——三大编程范式的边界在哪
设计模式
Zane19945 天前
策略模式现在该不该上?一次讲清楚过度设计和设计不足怎么找平衡
设计模式
她说..5 天前
常见设计模式-模板方法模式
java·spring·设计模式·springboot
xiaofeiyang1505 天前
第六章 · 桥接 — 三支毛笔,画出九种颜色
设计模式
Shadow(⊙o⊙)6 天前
OTOL设计模式 One Thread One Loop
服务器·网络·设计模式
sarasuki6 天前
如何让LLM 能在半夜偷偷打开网易云呢?
人工智能·设计模式·agent
小王师傅667 天前
【设计模式】装饰模式(四):框架源码实战——从 Java I/O 到 Spring 到 MyBatis
java·设计模式
执明wa7 天前
Android RecyclerView 多类型, 多种 Item
android·xml·开发语言·设计模式·android studio