《设计模式的艺术》笔记 - 状态模式

这篇具有很好参考价值的文章主要介绍了《设计模式的艺术》笔记 - 状态模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

介绍

        状态模式允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象,状态模式是一种对象行为模式。

实现

myclass.h

//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>
#include <memory>

class State {   // 抽象状态类
public:
    virtual void handle() = 0;
};

class Context { // 环境类
public:
    Context();
    void setState(const std::shared_ptr<State> &state);
    void request(int num);
    void changeState();

private:
    std::shared_ptr<State> m_state;
    int m_value;
};

class ConcreteStateA : public State {    // 具体状态类A
public:
    void handle() override;
};

class ConcreteStateB : public State {    // 具体状态类B
public:
    void handle() override;
};


#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"
#include <thread>
#include <unistd.h>
#include <sstream>

Context::Context() {
    m_value = 0;
    m_state.reset(new ConcreteStateA());
}

void Context::setState(const std::shared_ptr<State> &state) {
    m_state = state;
}

void Context::request(int num) {
    int tmp = m_value;
    m_value += num;
    if ((tmp >= 0 && m_value < 0) || (tmp < 0 && m_value >= 0)) {
        changeState();
    }
    m_state->handle();
}

void Context::changeState() {
    std::cout << "切换状态" << std::endl;
    if (m_value >= 0) {
        m_state.reset(new ConcreteStateA());
    } else {
        m_state.reset(new ConcreteStateB());
    }
}

void ConcreteStateA::handle() {
    std::cout << "ConcreteStateA::handle()" << std::endl;
}

void ConcreteStateB::handle() {
    std::cout << "ConcreteStateB::handle()" << std::endl;
}

main.cpp

#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    Context *context = new Context;
    context->request(0);
    std::cout << "-------------------" << std::endl;
    context->request(-10);
    std::cout << "-------------------" << std::endl;
    context->request(20);

    return 0;
}

总结

优点

        1. 封装了状态的转换规则。在状态模式中可以将状态的转换代码封装在环境类或者具体状态类中,对状态转换代码进行集中管理,而不是分散在一个个业务方法中。

        2. 将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。

        3. 允许状态转换逻辑与状态对象合成一体,而不是提供一个巨大的条件语句块。状态模式可以避免使用庞大的条件语句来将业务方法和状态转换代码交织在一起。

        4. 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点

        1. 状态模式的使用必然会增加系统中类和对象的个数,导致系统运行开销增大。

        2. 状态模式的程序结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,增加系统设计的难度。

        3. 状态模式对开闭原则的支持并不太好。增加新的状态类需要修改那些负责状态转换的源代码,否则无法转换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

适用场景

        1. 对象的行为依赖于它的状态(例如某些属性值),状态的改变将导致行为的变化。

        2. 在代码中包含大量与对象状态有关的条件语句。这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,并且导致客户类与类库之间的耦合增强。

练习

myclass.h

//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>
#include <memory>

class Level {   // 抽象状态类
public:
    virtual void play() = 0;
    virtual void doubleScore();
    virtual void changeCards();
    virtual void peekCards();
};

class CardsGame {
public:
    CardsGame();
    ~CardsGame();

    void play(int score);   // 模拟玩游戏得分
    void doubleScore();
    void changeCards();
    void peekCards();

private:
    Level *m_level;     // 当前等级
    Level *m_primary;   // 入门级
    Level *m_secondary; // 熟练级
    Level *m_professional;  // 高手级
    Level *m_final;     // 骨灰级
    int m_score;    // 得分
};

class PrimaryLevel : public Level {
public:
    void play() override;

    void doubleScore() override;

    void changeCards() override;

    void peekCards() override;
};

class SecondaryLevel : public Level {
public:
    void play() override;

    void changeCards() override;

    void peekCards() override;
};

class ProfessionalLevel : public Level {
public:
    void play() override;

    void peekCards() override;
};

class FinalLevel : public Level {
public:
    void play() override;
};


#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"
#include <thread>
#include <unistd.h>
#include <sstream>

void Level::doubleScore() {
    std::cout << "胜利积分加倍" << std::endl;
}

void Level::changeCards() {
    std::cout << "换牌" << std::endl;
}

void Level::peekCards() {
    std::cout << "偷看他人的牌" << std::endl;
}

CardsGame::CardsGame() {
    m_primary = new PrimaryLevel();
    m_secondary = new SecondaryLevel();
    m_professional = new ProfessionalLevel();
    m_final = new FinalLevel();
    m_level = m_primary;
    m_score = 0;
}

CardsGame::~CardsGame() {
    if (m_primary) {
        delete m_primary;
    }
    if (m_secondary) {
        delete m_secondary;
    }
    if (m_professional) {
        delete m_professional;
    }
    if (m_final) {
        delete m_final;
    }
}

void CardsGame::play(int score) {
    m_level->play();
    m_score += score;
    if (m_score < 100) {
        if (m_level != m_primary) {
            std::cout << "切换到入门级" << std::endl;
            m_level = m_primary;
        }
    } else if (m_score < 500) {
        if (m_level != m_secondary) {
            std::cout << "切换到熟练级" << std::endl;
            m_level = m_secondary;
        }
    } else if (m_score < 1000) {
        if (m_level != m_professional) {
            std::cout << "切换到高手级" << std::endl;
            m_level = m_professional;
        }
    } else {
        if (m_level != m_final) {
            std::cout << "切换到骨灰级" << std::endl;
            m_level = m_final;
        }
    }
}

void CardsGame::changeCards() {
    m_level->changeCards();
}

void CardsGame::doubleScore() {
    m_level->doubleScore();
}

void CardsGame::peekCards() {
    m_level->peekCards();
}

void PrimaryLevel::play() {
    std::cout << "入门级游戏开始" << std::endl;
}

void PrimaryLevel::doubleScore() {
    std::cout << "入门级不支持游戏胜利积分加倍功能" << std::endl;
}

void PrimaryLevel::changeCards() {
    std::cout << "入门级不支持换牌功能" << std::endl;
}

void PrimaryLevel::peekCards() {
    std::cout << "入门级不支持偷看他人的牌功能" << std::endl;
}

void SecondaryLevel::play() {
    std::cout << "熟练级游戏开始" << std::endl;
}

void SecondaryLevel::changeCards() {
    std::cout << "熟练级不支持换牌功能" << std::endl;
}

void SecondaryLevel::peekCards() {
    std::cout << "熟练级不支持偷看他人的牌功能" << std::endl;
}

void ProfessionalLevel::play() {
    std::cout << "高手级游戏开始" << std::endl;
}

void ProfessionalLevel::peekCards() {
    std::cout << "高手级不支持偷看他人的牌功能" << std::endl;
}

void FinalLevel::play() {
    std::cout << "骨灰级游戏开始" << std::endl;
}

main.cpp文章来源地址https://www.toymoban.com/news/detail-824368.html

#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    CardsGame *cardsGame = new CardsGame();
    cardsGame->doubleScore();
    cardsGame->changeCards();
    cardsGame->peekCards();
    cardsGame->play(200);
    std::cout << "------------------------" << std::endl;
    cardsGame->doubleScore();
    cardsGame->changeCards();
    cardsGame->peekCards();
    cardsGame->play(500);
    std::cout << "------------------------" << std::endl;
    cardsGame->doubleScore();
    cardsGame->changeCards();
    cardsGame->peekCards();
    cardsGame->play(500);
    std::cout << "------------------------" << std::endl;
    cardsGame->doubleScore();
    cardsGame->changeCards();
    cardsGame->peekCards();
    cardsGame->play(0);

    delete cardsGame;

    return 0;
}

到了这里,关于《设计模式的艺术》笔记 - 状态模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《设计模式的艺术》笔记 - 组合模式

            组合模式组合多个对象形成树形结构以表示具有“部分-整体”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,又可以称为“部分—整体”(Part-Whole)模式,它是一种对象结构型模式。 myclass.h myclass.cpp main.cpp  

    2024年01月19日
    浏览(38)
  • 《设计模式的艺术》笔记 - 代理模式

            代理模式是给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式是一种对象结构型模式。 myclass.h myclass.cpp main.cpp         1. 代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度,满足迪米特法则。         2. 客户端可以

    2024年01月19日
    浏览(46)
  • 《设计模式的艺术》笔记 - 桥接模式

            桥接模式将抽象部分与其实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体模式或接口模式 myclass.h myclass.cpp main.cpp         1. 分离抽象接口及其实现部分。桥接模式使用“对象间的关联关系”解耦了抽象和实现之间固有的绑定关系,

    2024年01月18日
    浏览(45)
  • 《设计模式的艺术》笔记 - 命令模式

            命令模式将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为模式,其别名为动作模式或事务模式。 myclass.h myclass.cpp main.cpp         只需要增加一个CommandQueue类即可

    2024年01月20日
    浏览(44)
  • 《设计模式的艺术》笔记 - 享元模式

            享元模式运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,是一种对象结构型模式。 myclass.

    2024年01月19日
    浏览(32)
  • 《设计模式的艺术》笔记 - 单例模式

            单例模式优点是可以确保系统中只存在单个对象实例,缺点是不便扩展,一定程度上违背单一原则,既提供业务方法,又提供创建对象方法         在类加载的时候就创建好对象,获取对象时直接返回即可         在类加载的时候没有创建对象,第一次获取对象

    2024年02月02日
    浏览(32)
  • 《设计模式的艺术》笔记 - 工厂方法模式

            在简单工厂模式中,当系统中需要引入新的产品时,由于静态工厂方法通过所传入的参数的不同来创建不同的产品,这必定要修改工厂类的源代码,将违背开闭原则。因此,工厂方法模式应运而生。工厂方法模式是定义一个用于创建对象的接口,让子类决定将哪一个

    2024年01月23日
    浏览(37)
  • 《设计模式的艺术》笔记 - 抽象工厂模式

            提供了一个创建一系列相关或相互依赖的对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。         在抽象工厂模式中,每个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品,这些产品构成了一个产品族。

    2024年01月16日
    浏览(29)
  • 《设计模式的艺术》笔记 - 建造者模式

            建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造这模式是一种对象创建型模式。 myclass.h myclass.cpp main.cpp         优点:         1. 在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建

    2024年01月16日
    浏览(31)
  • 《设计模式的艺术》笔记 - 简单工厂模式

            定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有相同的父类。因为在简单工厂模式中用于创建实例的方法是静态方法,因此简单工厂模式又被称为静态工厂方法模式,属于类创建型模式         将Factory合并到父类Product中,此时

    2024年01月16日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包