(状态模式

  • 一、概述
    • 二、结构
      • 三、实例
      • 四、适用场景
      • 五、优缺点

一、概述

描述:一天有早中晚,不同时间下,太阳光是不一样的。所以随着早中晚的状态变化,太阳的行为也随着变化。

定义:状态模式是一种行为设计模式, 让你能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。这其实就有点类似算法中的有限状态机的形式。

其主要思想是程序在任意时刻仅可处于几种有限的状态中。 在任何一个特定状态中, 程序的行为都不相同, 且可瞬间从一个状态切换到另一个状态。 不过, 根据当前状态, 程序可能会切换到另外一种状态, 也可能会保持当前状态不变。 这些数量有限且预先定义的状态切换规则被称为转移。

二、结构

  1. 上下文(Context)保存了对于一个具体状态对象的引用,并会将所有与该状态相关的工作委派给它。上下文通过状态接口与状态对象交互,且会提供一个设置器用于传递新的状态对象。

  2. 状态(State)接口会声明特定于状态的方法。这些方法应能被其他所有具体状态所理解,因为你不希望某些状态所拥有的方法永远不会被调用。

  3. 具体状态(Concrete States)会自行实现特定于状态的方法。为了避免多个状态中包含相似代码,你可以提供一个封装有部分通用行为的中间抽象类。状态对象可存储对于上下文对象的反向引用。状态可以通过该引用从上下文处获取所需信息,并且能触发状态转移。

  4. 上下文和具体状态都可以设置上下文的下个状态,并可通过替换连接到上下文的状态对象来完成实际的状态转换。

三、实例

#include<iostream>
#include<string>
#include<cstdio>
#include<memory>
using namespace std;class AbstractState;// 论坛账号
class ForumAccount {private:shared_ptr<AbstractState> state_;string name_;
public:explicit ForumAccount(string name);void set_state(shared_ptr<AbstractState> state) {state_ = state;}shared_ptr<AbstractState> get_state() {return state_;}string get_name() {return name_;}void downloadFile(int score);void writeNote(int score);void replyNote(int score);};class AbstractState {protected:ForumAccount* account_;int point_;string state_name_;
public:virtual void checkState() = 0;void set_point(int point) {point_ = point;}int get_point() {return point_;}void set_state_name(string name) {state_name_ = name;}string get_state_name() {return state_name_;}ForumAccount* get_account() {return account_;}virtual void downloadFile(int score) {printf("%s下载文件, 扣除%d积分。\n", account_->get_name().c_str(), score);point_ -= score;checkState();printf("%s剩余积分为%d, 当前级别为%s。\n", account_->get_name().c_str(), point_, account_->get_state()->get_state_name().c_str());}virtual void writeNote(int score) {printf("%s发布留言, 增加%d积分。\n", account_->get_name().c_str(), score);point_ += score;checkState();printf("%s剩余积分为%d, 当前级别为%s。\n", account_->get_name().c_str(), point_, account_->get_state()->get_state_name().c_str());}virtual void replyNote(int score) {printf("%s回复留言, 增加%d积分。\n", account_->get_name().c_str(), score);point_ += score;checkState();printf("%s剩余积分为%d, 当前级别为%s。\n", account_->get_name().c_str(), point_, account_->get_state()->get_state_name().c_str());}
};// 具体状态类: 新手
class PrimaryState : public AbstractState {public:explicit PrimaryState(AbstractState* state) {account_ = state->get_account();point_ = state->get_point();state_name_ = "新手";}explicit PrimaryState(ForumAccount* account) {account_ = account;point_ = 0;state_name_ = "新手";}void downloadFile(int score) override {printf("对不起, %s没有下载文件的权限!\n", account_->get_name().c_str());}void checkState() override;
};// 具体状态类: 高手
class MiddleState : public AbstractState {public:explicit MiddleState(AbstractState* state) {account_ = state->get_account();point_ = state->get_point();state_name_ = "高手";}void writeNote(int score) override {printf("%s发布留言, 增加%d积分。\n", account_->get_name().c_str(), score * 2);point_ += score * 2;checkState();printf("%s剩余积分为%d, 当前级别为%s。\n", account_->get_name().c_str(), point_, account_->get_state()->get_state_name().c_str());}void checkState() override;
};// 具体状态类: 专家
class HighState : public AbstractState {public:explicit HighState(AbstractState* state) {account_ = state->get_account();point_ = state->get_point();state_name_ = "专家";}void writeNote(int score) override {printf("%s发布留言, 增加%d积分。\n", account_->get_name().c_str(), score * 2);point_ += score * 2;checkState();printf("%s剩余积分为%d, 当前级别为%s。\n", account_->get_name().c_str(), point_, account_->get_state()->get_state_name().c_str());}virtual void downloadFile(int score) {printf("%s下载文件, 扣除%d积分。\n", account_->get_name().c_str(), score / 2);point_ -= score / 2;checkState();printf("%s剩余积分为%d, 当前级别为%s。\n", account_->get_name().c_str(), point_, account_->get_state()->get_state_name().c_str());}void checkState() override;
};void PrimaryState::checkState() {if (point_ >= 1000) {account_->set_state(make_shared<HighState>(this));}else if (point_ >= 100) {account_->set_state(make_shared<MiddleState>(this));}
}void MiddleState::checkState() {if (point_ >= 1000) {account_->set_state(make_shared<HighState>(this));}else if (point_ < 100) {account_->set_state(make_shared<PrimaryState>(this));}
}void HighState::checkState() {if (point_ < 100) {account_->set_state(make_shared<PrimaryState>(this));}else if (point_ < 1000) {account_->set_state(make_shared<HighState>(this));}
}ForumAccount::ForumAccount(std::string name): name_(name), state_(make_shared<PrimaryState>(this)) {printf("账号%s注册成功!\n", name.c_str());
}void ForumAccount::downloadFile(int score) {state_->downloadFile(score);
}void ForumAccount::writeNote(int score) {state_->writeNote(score);
}void ForumAccount::replyNote(int score) {state_->replyNote(score);
}int main() {// 注册新用户ForumAccount account("TOMOCAT");account.writeNote(20);account.downloadFile(20);account.replyNote(100);account.writeNote(40);account.downloadFile(80);account.writeNote(1000);account.downloadFile(80);return 0;
}

四、适用场景

  1. 对象需要根据自身当前状态进行不同行为,同时状态的数量非常多且与状态相关的代码会频繁变更的话,可使用状态模式。
  2. 某个类需要根据成员变量的当前值改变自身行为,从而需要使用大量的条件语句时,可使用该模式。
  3. 当相似状态和基于条件的状态机转换中存在许多重复代码时,可使用状态模式。

五、优缺点

优点:

  1. 单一职责原则。将与特定状态相关的代码放在单独的类中。
  2. 开闭原则。无需修改已有状态类和上下文就能引入新状态。
  3. 通过消除臃肿的状态机条件语句简化上下文代码。

缺点:

  1. 如果状态机只有很少的几个状态,或者很少发生改变,那么应用该模式可能会显得小题大作。

State(状态模式)行为型相关推荐

  1. 设计模式21:State 状态模式(行为型模式)

    State 状态模式(行为型模式) 动机(Motivation) 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态的行为就可能完全不同. ...

  2. 5.8 设计模式之State(状态)—对象行为型模式

    5.8 State(状态)-对象行为型模式 参考文章 意图 状态模式是一种行为设计模式, 改变一个对象的内部状态进而改变其行为. 问题及情景 状态模式与有限状态机的概念紧密相关. 其主要思想是程序在任 ...

  3. 设计模式之 State(状态模式)通俗理解

    23种设计模式 1 State 模式的定义 不同的状态,不同的行为;或者说,每个状态有着相应的行为. 2 何时使用? 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了它的类.状态模式 ...

  4. 设计模式与泡mm的关系之state状态模式及再思考

    我跑我跑我跑 网上原文如下: 20.State,跟mm交往时,一定要注意她的状态哦,在不同的状态时她的行为会有不同,比如你约她今天晚上去看电影,对你没兴趣的mm就会说"有事情啦", ...

  5. Java 设计模式之 State 状态模式

    状态模式用于根据状态决定行为的场景. 比如一个人处于不同的心情时,会说不同的话,会做不同的事情,说话和做事由状态决定. 这里可以将心情设计为一个抽象类,开心,伤心,抑郁时的说话,做事的行为作为抽象方法 ...

  6. 设计模式之状态模式(State)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  7. Java设计模式-状态模式(State)

    核心思想就是:当对象的状态改变时,同时改变其行为,很好理解!就拿QQ来说,有几种状态,在线.隐身.忙碌等,每个状态对应不同的操作,而且你的好友也能看到你的状态,所以,状态模式就两点:1.可以通过改变状 ...

  8. 设计模式---状态模式(State Pattern)

    目录 1.App抽奖活动问题 2.状态模式基本介绍 3.原理类图 4.状态模式解决APP抽奖活动问题 5.注意事项和细节 1.App抽奖活动问题 请编写程序完成APP抽奖活动,具体抽奖要求如下: 假如 ...

  9. 大话设计模式—状态模式

    在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象. 大话设 ...

最新文章

  1. 从源代码编译里程碑的 ICS ROM
  2. js中Window跟window的区别
  3. 基于FPGrowth挖掘算法的乳腺癌中医症型关联规则挖掘
  4. 产品经理网站数据分析之测量问题现状(二)
  5. 五款常用邮件管理系统评测
  6. 手摸手Go 深入剖析sync.Pool
  7. 快速上手友盟推送前后端
  8. 计算机专业改动漫设计,《计算机动漫与游戏制作》专业课程体系改革方案.doc...
  9. 计算机应用与篮球有关的文章,浅析计算机技术应用对高校篮球教学的作用与影响...
  10. 五子棋java源代码博客园_来来来,五子棋源代码
  11. K8S学习笔记之为什么需要Pod?
  12. 蓝桥杯练习题之圆的面积
  13. bzoj1127 洛谷3474 题解
  14. 【Pytorch实战4】基于CIFAR10数据集训练一个分类器
  15. 元宇宙产业委共同主席倪健中带队参访杭州市总工会推动元宇宙合作
  16. 请问开发手机游戏需要什么软件?
  17. SpringCloud微服务架构实战:商家权限体系设计及开发
  18. javaScript中三大家族总结
  19. 【深度学习】深度学习简介
  20. VBA: 什么是多维数组:从4维数组说起。兼3维数组和数组嵌套的区别

热门文章

  1. Java数组和冒泡排序
  2. 太厉害了!java线程死锁例子
  3. 【深度学习】使用深度学习进行自动车牌检测和识别
  4. 晨曦中,凛冽的风,脑际空空,可记得痛
  5. 无代码系统搭建“服装行业管理系统”
  6. C#线程中使用委托方式设置控件属性
  7. 物联网供应商,主要面临哪些安全挑战?
  8. Bugku—come_game
  9. 两台电脑ping不通的解决方案
  10. 大咖对话 | 企业数字化转型破局之道