【c++学习记录】状态模式,实现一个登陆功能

状态模式建议为对象的所有可能状态新建一个类, 然后将所有状态的对应行为抽取到这些类中。

原始对象被称为上下文 (context), 它并不会自行实现所有行为, 而是会保存一个指向表示当前状态的状态对象的引用, 且将所有与状态相关的工作委派给该对象。如需将上下文转换为另外一种状态, 则需将当前活动的状态对象替换为另外一个代表新状态的对象。 采用这种方式是有前提的: 所有状态类都必须遵循同样的接口, 而且上下文必须仅通过接口与这些对象进行交互。

markdowm 复制代码
+-------------------+
|     Context       |
+-------------------+
| - currentState    |
| + setState()      |
| + userInput()     |
+-------------------+

         ▲
         │
+--------│---------------------------------------------+
│        ▼                                             │
│  +----------------+                                   │
│  |     State      | <abstract>                        │
│  +----------------+                                   │
│  | + enter()      |                                   │
│  | + handleInput()| <pure virtual>                    │
│  +----------------+                                   │
│                                                       │
│     ▲              ▲               ▲                 ▲ │
│     │              │               │                 │ │
│ +-----------+ +------------+ +-----------+ +----------------+ 
│ | NotLoggedIn | | InputPassword | | LoggingIn | | LoggedIn | ...
│ +-----------+ +------------+ +-----------+ +----------------+ 
cpp 复制代码
#include <iostream>
#include <string>

class LoginContext; // 前向声明

// 抽象状态类
class LoginState {
public:
    virtual ~LoginState() = default;
    virtual void enter(LoginContext* context) = 0; // 进入状态时的行为
    virtual void handleInput(LoginContext* context, const std::string& input) = 0; // 处理输入
};

// 前向声明所有具体状态类
class NotLoggedInState;
class InputtingPasswordState;
class LoggingInState;
class LoggedInState;
class LoginFailedState;

// 上下文类
class LoginContext {
private:
    LoginState* currentState;
    std::string username;
    std::string password;

public:
    LoginContext() : currentState(nullptr) {}

    ~LoginContext() {
        delete currentState; // 释放状态资源
    }

    void setState(LoginState* state) {
        if (currentState != nullptr) {
            delete currentState; // 释放旧状态资源
        }
        currentState = state;
        if (currentState != nullptr) {
            currentState->enter(this); // 自动触发进入逻辑
        }
    }

    void userInput(const std::string& input) {
        if (currentState != nullptr) {
            currentState->handleInput(this, input);
        }
    }

    const std::string& getUsername() const { return username; }
    void setUsername(const std::string& name) { username = name; }

    const std::string& getPassword() const { return password; }
    void setPassword(const std::string& pwd) { password = pwd; }
};

// 具体状态类定义
class NotLoggedInState : public LoginState {
public:
    void enter(LoginContext* context) override {
        std::cout << "进入未登录状态,请输入用户名和密码。\n";
    }
    void handleInput(LoginContext* context, const std::string& input) override;
};

class InputtingPasswordState : public LoginState {
public:
    void enter(LoginContext* context) override {
        std::cout << "请输入密码:\n";
    }
    void handleInput(LoginContext* context, const std::string& input) override;
};

class LoggingInState : public LoginState {
public:
    void enter(LoginContext* context) override;
    void handleInput(LoginContext* /*context*/, const std::string& /*input*/) override {}
};

class LoggedInState : public LoginState {
public:
    void enter(LoginContext* context) override {
        std::cout << "[状态] 登录成功!欢迎回来。" << std::endl;
    }
    void handleInput(LoginContext* /*context*/, const std::string& /*input*/) override {}
};

class LoginFailedState : public LoginState {
public:
    void enter(LoginContext* context) override {
        std::cout << "[状态] 登录失败,请重新输入用户名。" << std::endl;
        context->setState(new NotLoggedInState());
    }
    void handleInput(LoginContext* /*context*/, const std::string& /*input*/) override {}
};

// 状态类成员函数实现(解决循环依赖)
void NotLoggedInState::handleInput(LoginContext* context, const std::string& input) {
    std::cout << "请输入用户名:" << std::endl;
    context->setUsername(input);
    context->setState(new InputtingPasswordState());
}

void InputtingPasswordState::handleInput(LoginContext* context, const std::string& input) {
    context->setPassword(input);
    std::cout << "正在登陆...\n";
    context->setState(new LoggingInState());
}

void LoggingInState::enter(LoginContext* context) {
    std::cout << "[状态] 当前状态:登录中" << std::endl;

    // 模拟登录验证
    const std::string user = context->getUsername();
    const std::string pass = context->getPassword();

    if (user == "admin" && pass == "123456") {
        context->setState(new LoggedInState());
    }
    else {
        context->setState(new LoginFailedState());
    }
}

//int main() {
//    LoginContext context;
//    context.setState(new NotLoggedInState());
//
//    // 模拟用户输入流程
//    context.userInput("admin");     // 输入用户名
//    context.userInput("wrongpass"); // 输入错误密码
//    context.userInput("admin");     // 再次输入用户名
//    context.userInput("123456");    // 输入正确密码
//
//    return 0;
//}
int main() {
    LoginContext context;
    context.setState(new NotLoggedInState());

    std::string input;
    while (true) {
        std::cout << "> ";
        std::getline(std::cin, input);

        if (input == "exit") break;

        context.userInput(input);
    }

    return 0;
}
相关推荐
dear_bi_MyOnly8 小时前
【MyBatis 操作数据库】
java·数据库·学习·mybatis·学习方法
一只小菜鸡..9 小时前
南京大学 操作系统 (JYY) 学习笔记:从 UNIX 到 Linux 与庞大的应用生态
笔记·学习·unix
MartinYeung510 小时前
[论文学习]迈向自主医疗人工智能智能体:MIRA系统深度分析
人工智能·学习
熊猫钓鱼>_>11 小时前
ArkTS 装饰器总览:V1 / V2 / 通用装饰器完整学习笔记
笔记·学习·华为·交互·harmonyos·arkts·arkweb
拳里剑气12 小时前
C++算法:多源BFS
c++·算法·宽度优先·多源bfs
ysa05103013 小时前
【板子】短序列dp(换成维护更小常数维度的dp)
c++·笔记·算法·板子
茯苓gao15 小时前
嵌入式开发笔记:CAN与CAN FD完全指南——从帧格式差异到MCU选型实战
网络·笔记·stm32·嵌入式硬件·学习·汽车
aramae15 小时前
C++ IO流完全指南:从C标准库到C++流式编程
服务器·c语言·开发语言·c++·后端
木木_王15 小时前
嵌入式学习 | STM32 裸板驱动开发(Day06) | DHT11温湿度传感器超详解(单总线时序+全套驱动代码+智能温湿度报警项目)
驱动开发·stm32·学习
_wyt00115 小时前
c++里的族谱:树
c++·