我所理解的设计模式(C++实现)——状态模式(State Pattern)
概述:
看看我们平时用的开关,同样一个开关他有2种状态:开和关,当她处于不同的状态的时候她的行为是不一样的,比如当她是开着的时候,你按她一下,她就变成了关闭状态,她是关着的时候按她一下,她就变成了开着的状态。看上去就像是改变了它的类一样,其实我们开发者都知道,我们里面用到了if-else,但是当碰到更多状态时就会造成很多很多if-else,设计和维护就相当的复杂,我们将要学习的状态模式就是允许一个对象在其内部状态改变时改变它的行为,使对象看起来似乎修改了它的类。
类图和实例:
上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete State对象来处理。
抽象状态(State):定义一个接口以封装使用上下文环境的的一个特定状态相关的行为。
具体状态(Concrete State):实现抽象状态定义的接口。
这里我们举星际争霸里的坦克作为例子,它不架起来的时候可以攻击,可以移动。架起来的时候攻击增强,但是不能移动:
#include <iostream>
class SiegeTank;
class ISiegeTankState
{
public:
virtual void move(int x, int y) = 0;
virtual void attack() = 0;
}; class SiegeState : public ISiegeTankState
{
public:
SiegeState(SiegeTank* pTank): m_pTank(pTank){} virtual void move(int x, int y)
{
std::cout << "Can't move in siege mode." << std::endl;
} virtual void attack()
{
std::cout << "Attacking for 40" << std::endl;
} private:
SiegeTank* m_pTank;
}; class TankState : public ISiegeTankState
{
public:
TankState(SiegeTank* pTank): m_pTank(pTank){} virtual void move(int x, int y)
{
std::cout << "Move to (" << x << ", " << y << ")" << std::endl;
} virtual void attack()
{
std::cout << "Attacking for 20" << std::endl;
} private:
SiegeTank* m_pTank;
}; class SiegeTank
{
public:
SiegeTank()
{
m_pTankState = new TankState(this);
m_pSiegeState = new SiegeState(this);
m_pSiegeTankState = m_pTankState;
} void enterTankMode()
{
m_pSiegeTankState = m_pTankState;
std::cout << "Switch to tank mode" << std::endl;
} void enterSiegeMode()
{
m_pSiegeTankState = m_pSiegeState;
std::cout << "Switch to siege mode" << std::endl;
} public:
void attack()
{
m_pSiegeTankState->attack();
} void move(int x, int y)
{
m_pSiegeTankState->move(x, y);
} private:
void setState(ISiegeTankState* pSiegeTankMode)
{
m_pSiegeTankState = pSiegeTankMode;
} private:
TankState* m_pTankState;
SiegeState* m_pSiegeState;
ISiegeTankState* m_pSiegeTankState;
}; int main()
{
SiegeTank tank;
tank.enterTankMode();
tank.attack();
tank.move(1, 1); tank.enterSiegeMode();
tank.attack();
tank.move(2, 2); tank.enterTankMode();
tank.attack();
tank.move(3, 3); return 0;
}
解决的问题:
状态模式主要解决的是当控制一个对象状态装换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简单化。
当一个对象行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
优缺点:
优点
1,状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
2,所有状态相关的代码都存在于某个ConcereteState中,所以通过定义新的子类很容易地增加新的状态和转换。
3,状态模式通过把各种状态转移逻辑分不到State的子类之间,来减少相互间的依赖。
缺点
1,状态模式的使用必然会增加系统类和对象的个数。
2,状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
LCL_data原创于CSDN.NET【http://blog.csdn.net/lcl_data/article/details/10248415】
更多设计模式文章请参考:我所理解的设计模式
我所理解的设计模式(C++实现)——状态模式(State Pattern)的更多相关文章
- 乐在其中设计模式(C#) - 状态模式(State Pattern)
原文:乐在其中设计模式(C#) - 状态模式(State Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 状态模式(State Pattern) 作者:webabcd 介绍 允 ...
- 二十四种设计模式:状态模式(State Pattern)
状态模式(State Pattern) 介绍允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它所属的类. 示例有一个Message实体类,对它的操作有Insert()和Get()方法, ...
- 状态模式-State Pattern(Java实现)
状态模式-State Pattern 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. State接口 ...
- 设计模式(十二):通过ATM取款机来认识“状态模式”(State Pattern)
说到状态模式,如果你看过之前发布的重构系列的文章中的<代码重构(六):代码重构完整案例>这篇博客的话,那么你应该对“状态模式”并不陌生,因为我们之前使用到了状态模式进行重构.上一篇博客我们 ...
- [设计模式] 20 状态模式 State Pattern
在GOF的<设计模式:可复用面向对象软件的基础>一书中对状态模式是这样说的:允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它的类.状态模式的重点在于状态转换,很多时候,对 ...
- 【UE4 设计模式】状态模式 State Pattern
概述 描述 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类. 其别名为状态对象(Objects for States),状态模式是一种对象行为型模式. 有限状态机(FSMs) ...
- C#设计模式——状态模式(State Pattern)
一.概述在面向对象软件设计时,常常碰到某一个对象由于状态的不同而有不同的行为.如果用if else或是switch case等方法处理,对象操作及对象的状态就耦合在一起,碰到复杂的情况就会造成代码结构 ...
- [设计模式-行为型]状态模式(State)
一句话 在一个类的对象中维护状态的类的对象 概括
- 《JAVA设计模式》之状态模式(State)
在阎宏博士的<JAVA与模式>一书中开头是这样描述状态(State)模式的: 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为 ...
- 十一个行为模式之状态模式(State Pattern)
定义: 当一个对象有多个状态,并且在每个状态下有不同的行为,可以使用状态模式来在其内部改变状态时改变其行为,而客户端不会察觉状态的改变,仍使用同样的方法或接口与对象进行交互. 结构图: Context ...
随机推荐
- [OGRE]看备注学编程(02):打地鼠01-布置场地九只地鼠
项目下载地址:http://download.csdn.net/detail/wxg694175346/6340347 头文件ShrewMouseApplication.h: #ifndef __Sh ...
- [React Testing] className with Shallow Rendering
The React Shallow Renderer test utility lets us inspect the output of a component one level deep. In ...
- 秒杀多线程第八篇 经典线程同步 信号量Semaphore
阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <且不超过最大资源数量. 第三个參数能够用来传出先前的资源计数,设为NULL表示不须要传出. 注意:当 ...
- C#调用R语言输出图片
参考:http://rdotnet.codeplex.com/documentation REngine.SetEnvironmentVariables(); REngine engine = R ...
- 苹果的HomeKit协议
苹果的HomeKit协议非常底层,其作用仅限于让iOS平台和家居设备能够相互“握手”,但“认识”之后,想要继续控制灯.空调等设备,仍然需要家电厂商在HomeKit的基础上进行二次开发.
- Android文字的复制和粘贴
Android中提供了简单的额复制粘贴功能.代码很简单 复制文字的代码: ClipboardManager cbm= (ClipboardManager) MainActivity.this .get ...
- JAVA设置环境变量和在DOS下运行java程序
在学校实训的这几天,老师带着我们开始深入的复习java.这是第一天的内容哦 对于“JAVA设置环境变量和在DOS下运行java程序”,许多初学者是陌生的,但了解这个却对后期的学习很重要. http:/ ...
- 移动端(IOS)iframe监听不到 onscroll 事件
问题描述: 我在一个页面A中有瀑布流,点击瀑布流中的图片需要进入到另外一个页面B,点击返回需要回到页面A中点击的位置,为了实现该效果所以在页面A中嵌入iframe,iframe指向页面B,页面B中同样 ...
- 使用VS Code开发Angular 2应用程序所需配置文件的解析
目录 package.json typings.json tsconfig.json launch.json settings.json tasks.json package.json: 这是项目的基 ...
- Android -------- RelativeLayout 和 LinearLayout 的性能分析
布局的绘制角度 RelativeLayout不如LinearLayout快的根本原因是: RelativeLayout需要对其子View进行两次measure过程, 而LinearLayout则只需一 ...