zoukankan      html  css  js  c++  java
  • 状态模式

    状态模式

    1. 概述

      状态模式,就是将对象的状态和对应状态下的行为分离开来,不再是简单的if…else或switch…case分支结构了,而是每一个状态都对应一个类,一个类集中管理一个状态;在多状态的情况下,简化了程序的维护和管理,让程序结构简明化,同时也易于扩展。

    2. 解决的问题

      当控制一个对象状态转换的条件表达式过于复杂时的情况。

    3. 模式中的角色

      1) 上下文环境(Context):定义了客户程序所需接口并维护一个具体状态角色实例,将与状态相关的操作委托给当前的ConcreteState对象处理。

      2) 抽象状态(State):定义一个接口以封装使用上下文环境的的一个特定状态相关的行为。

      3) 具体状态(Concrete State):实现抽象状态定义的接口。

    4. 优点

      1) 状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。

      2) 所有状态相关的代码都存在于某个ConcereteState中,所以通过定义新的子类很容易地增加新的状态和转换。

      3) 状态模式通过把各种状态转移逻辑分不到State的子类之间,来减少相互间的依赖。

    5. 缺点

      1) 导致较多的ConcreteState子类

    6. 适用场景

      下面是GOF在《设计模式》中给出的状态模式的适用情况:

      1) 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。

      2) 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。

    7. 与策略模式的比较

      下面是策略模式和方法模式的UML图

                                   

      二者外表一样,只是二者的关注点不一样:

      1) 策略模式关注行为的变化,但归根结底只有一个行为,变化的只是行为的实现。客户不关注这些.当新增变化时对客户可以没有任何影响。

      2) 状态模式同样关注行为的变化,但这个变化是由状态来驱动,一般来说每个状态和行为都不同。客户需要关注新增的状态或行为与已有的不同。

      状态模式一个形象的比喻是”饱了睡,饿了吃”.在这里”饱和饿”是两种状态,”睡和吃”是两种行为.

     

    8.代码实现

    1)用if...else的情况

     1 typedef enum tagState
     2 {
     3     state,
     4     state1,
     5     state2
     6 }State;
     7 
     8 void Action(State actionState)
     9 {
    10     if (actionState == state)
    11     {
    12          // DoSomething
    13     }
    14     else if (actionState == state1)
    15     {
    16          // DoSomething
    17     }
    18     else if (actionState == state2)
    19     {
    20          // DoSomething
    21     }
    22     else
    23     {
    24          // DoSomething
    25     }
    26 }

    2)用状态模式表现--分离状态和行为

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class Context;
     5 class State
     6 {
     7 public:
     8     virtual void Handle(Context *pContext) = 0;
     9 };
    10 
    11 class ConcreteStateA : public State
    12 {
    13 public:
    14     virtual void Handle(Context *pContext)
    15     {
    16          cout<<"I am concretestateA."<<endl;
    17     }
    18 };
    19 class ConcreteStateB : public State
    20 {
    21 public:
    22     virtual void Handle(Context *pContext)
    23     {
    24          cout<<"I am concretestateB."<<endl;
    25     }
    26 };
    27 
    28 class Context
    29 {
    30 public:
    31     Context(State *pState) : m_pState(pState){}
    32     void Request()
    33     {
    34          if (m_pState)
    35          {
    36               m_pState->Handle(this);
    37          }
    38     }
    39      void ChangeState(State *pState)
    40     {
    41          m_pState = pState;
    42     }
    43 private:
    44     State *m_pState;
    45 };
    46 
    47 int main()
    48 {
    49     State *pStateA = new ConcreteStateA();
    50     State *pStateB = new ConcreteStateB();
    51     Context *pContext = new Context(pStateA);
    52 
    53     pContext->Request();
    54     pContext->ChangeState(pStateB);
    55     pContext->Request();
    56 
    57     delete pContext;
    58     delete pStateB;
    59     delete pStateA;
    60 }

    3)状态模式--旋转开关

      "一般的状态判断"如:

        if (which==1) state="hello";     

        else if (which==2) state="hi";     

        else if (which==3) state="bye";

      如果改成:

        if (state.euqals("bye")) state="hello";     

        else if (state.euqals("hello")) state="hi";     

        else if (state.euqals("hi")) state="bye";

      这就是 "开关切换状态",是将state的状态从"hello"切换到"hi",再切换到""bye";在切换到"hello",好象一个旋转开关,这种状态改变就可以使用State模式了.

    .h文件:

     1 class Context;
     2 class State
     3 {
     4 public:
     5     virtual void Handle(Context* pContext)=0;
     6 };
     7 
     8 class ConcreteStateA : public State
     9 {
    10 public:
    11     virtual void Handle(Context* pContext);
    12 };
    13 
    14 class ConcreteStateB : public State
    15 {
    16 public:
    17     virtual void Handle(Context* pContext);
    18 };
    19 
    20 class ConcreteStateC : public State
    21 {
    22 public:
    23     virtual void Handle(Context* pContext);
    24 };
    25 
    26 class Context
    27 {
    28 public:
    29     Context(State* pState): m_pState(pState){}
    30     void Request()
    31     {
    32         if(m_pState)
    33     {
    34         m_pState->Handle(this);
    35     }
    36     }
    37     void ChangeState(State* pState)
    38     {
    39         m_pState = pState;
    40     }
    41 
    42 private:
    43     State* m_pState;
    44 };

    .cpp文件

     1 //执行该状态的行为并改变状态
     2 void ConcreteStateA::Handle(Context* pContext)
     3 {
     4     cout << "ConcreteStateA" << endl; 5     pContext->ChangeState(new ConcreteStateB());
     6 }
     7 
     8 //执行该状态的行为并改变状态
     9 void ConcreteStateB::Handle(Context* pContext)
    10 {
    11     cout << "ConcreteStateB" << endl;12     pContext->ChangeState(new ConcreteStateC());
    13 }
    14 
    15 //执行该状态的行为并改变状态
    16 void ConcreteStateC::Handle(Context* pContext)
    17 {
    18     cout << "ConcreteStateC" << endl;
    19     pContext->ChangeState(new ConcreteStateA());
    20 }

    客户端:

     1 #include "State.h"
     2 
     3 int main()
     4 {
     5     State* pState = new ConcreteStateA();
     6     Context* pContext = new Context(pState);
     7     pContext->Request();
     8     pContext->Request();
     9     pContext->Request();
    10     pContext->Request();
    11     pContext->Request();
    12     return 0;
    13 }
  • 相关阅读:
    https://github.com/cykl/infoqscraper/
    C# 笔记
    json.org
    python html parse
    doxygen
    review board
    ruunlevel debian
    连接REDIS
    composer
    php需要注意的地方
  • 原文地址:https://www.cnblogs.com/SnailProgramer/p/4249794.html
Copyright © 2011-2022 走看看