我所理解的设计模式(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 ...
随机推荐
- appium新版本不支持findElementByName,切换到findElementByAndroidUIAutomator
appium 1.7.6 不支持findElementByName(locator) 不知道为什么? 脚本中许多这样的语句,麻烦事情多了 org.openqa.selenium.InvalidSel ...
- 设置UIScrollView只可以水平或者竖直滚动
UIScrollView里边包含多个UIWebView: 可以通过设置contentSize的值,设置其width为UIScrollerView可视区域的宽度:即UIScrollView的width, ...
- Java基础(十)内部类
1.使用内部类的原因(3点) ①内部类方法可以访问该内部类定义所在的作用域中的数据,包括私有数据. ②内部类可以对同一个包中的其他类隐藏起来. ③当想要定义一个回调函数且不想编写大量代码时,使用匿名内 ...
- [Polymer] Custom Elements: Styling
Code: <dom-module id="business-card"> <template> <div class="card" ...
- Linux以KB显示内存大小
Linux以KB显示内存大小 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ free -k total used free shared buffers ca ...
- WEB服务健康状态检测
#!/bin/sh #date:2015-12-07 #filename:check_web.sh #作者:lixingli #Email:1162572407@qq.com #version:v1. ...
- django: form fileupload - 2
继续介绍文件上传的第二种形式和第三种形式. ------------------------------------------------------------- 第二种形式较简单,直接用 DB ...
- DataSet与DataTable的区别
DataSet:数据集.一般包含多个DataTable,用的时候,dataset["表名"]得到DataTable DataTable:数据表. 一: SqlDataAdapter ...
- 使用idea将本地项目上传至github及clone
一.上传 1.firl->settings 设置git 2.firl->settings 填写自己的登录名和密码,可以使用test测试是否连接成功 3. 就搞定了.github会自动建立一 ...
- 基于live555的一个简单RTSP服务器
1,编译live555源码目录下的 BasicUsageEnvironment.groupsock.liveMedia.UsageEnvironment四个工程生成相应的库文件: 目录结构如下: 2, ...