1. 程式人生 > >狀態模式(state)c++版本

狀態模式(state)c++版本

此為大話設計模式中的狀態模式的c++版本
因為此程式碼中各個類的相互依賴比較嚴重,所以加入了標頭檔案將宣告放置在標頭檔案之中
state.h

/*
 * state.h
 *
 *  Created on: Aug 10, 2017
 *      Author: [email protected]
 */

#ifndef _STATE_H_
#define _STATE_H_

#include <iostream>
#include <string>
class State;
//維護一個concreteState的例項,這個例項定義當前狀態
class Work
{
public
: //因為相互包含的問題實現在移至下方 Work(); void Set_state(State *s); //時間的設定和獲取函式 void Set_hour(double hour); double Get_hour(); void Write_program(); void Set_task_finished(bool finish); bool Get_task_finished(); private: State *_current; double _hour = 0; //任務狀態 bool
_finish = false; }; class State { public: virtual ~State(){} //定義一個工作介面交給子類實現 virtual void Write_program(Work *w){}; }; class ForenoonState:public State { public: void Write_program(Work *w) override; }; class NoonState:public State { public: //實現基類的工作函式 void Write_program(Work *w) override
; }; //下午工作類 class AfternoonState:public State { public: //實現基類的工作函式 void Write_program(Work *w) override; }; //傍晚工作類 class EveningState:public State { public: //實現基類的工作函式 void Write_program(Work *w) override; }; //睡眠類 class SleepingState:public State { public: //實現基類的工作函式 void Write_program(Work *w) override; }; //下班類 class RestState:public State { public: //實現基類的工作函式 void Write_program(Work *w) override; }; #endif /* _STATE_H_ */

state.cpp

/*
 * state.cpp
 *
 *  Created on: Aug 7, 2017
 *      Author: [email protected]
 *      狀態模式
 *      允許一個物件在其內部狀態改變時
 *      改變它的行為.物件看起來似乎修
 *      改了他的類.
 */

#include "state.h"
using namespace std;

void ForenoonState::Write_program(Work *w)
{
//檢查時間是否小於12點
    if(w->Get_hour() < 12)
    {
        cout<<"上午工作時間,精神飽滿!!時間:"<<w->Get_hour()<<endl;
    }else
    {
        //將指標設定為中午工作
        w->Set_state(new NoonState());
        //繼續呼叫WriteProgram函式檢查時間
        w->Write_program();
    }
}


void NoonState::Write_program(Work *w)
{
//檢查時間是否小於13點
    if(w->Get_hour() < 13)
    {
        cout<<"中午工作時間,餓了,吃飯!!時間:"<<w->Get_hour()<<endl;
    }else
    {
        //將指標設定為下午工作
        w->Set_state(new AfternoonState());
        //繼續呼叫WriteProgram函式檢查時間
        w->Write_program();
    }
}



void AfternoonState::Write_program(Work *w)
{
//檢查時間是否小於17點
    if(w->Get_hour() < 17)
    {
        cout<<"下午工作時間,精神還行!!時間:"<<w->Get_hour()<<endl;
    }else
    {
        //將指標設定為傍晚工作
        w->Set_state(new EveningState());
        //繼續呼叫WriteProgram函式檢查時間
        w->Write_program();
    }
}



void EveningState::Write_program(Work *w)
{
    //檢查任務是否完成
    if(w->Get_task_finished())
    {
        //如果是下班就轉入下班狀態
        w->Set_state(new RestState());
        w->Write_program();
    }else
    {
    //檢查時間是否小於21點
        if(w->Get_hour() < 21)
        {
            cout<<"加班中......時間:"<<w->Get_hour()<<endl;
        }else
        {
            //將指標設定為傍晚工作
            w->Set_state(new SleepingState());
            //繼續呼叫WriteProgram函式檢查時間
            w->Write_program();
        }
    }
}

void SleepingState::Write_program(Work *w)
{
//因為到深夜所以直接輸出吃不消
    cout<<"吃不消了,睡著了,時間:"<<w->Get_hour()<<endl;
}



void RestState::Write_program(Work *w)
{
//完成工作的輸出
    cout<<"下班回家,時間:"<<w->Get_hour();
}


//work類的建構函式實現
Work::Work()
{
//將上午工作的類的指標賦值給_current指標變數
    _current = new ForenoonState();
}

//用於修改_current指標變數
void Work::Set_state(State *s)
{
    _current = s;
}

//時間的設定和獲取函式
void Work::Set_hour(double hour)
{
    _hour = hour;
}

double Work::Get_hour()
{
    return _hour;
}

void Work::Write_program()
{
//用已經在建構函式被賦上ForenoonState類的地址的_current
//呼叫ForenoonState類的Write_program函式
//並且傳入Work類的地址讓其可以繼續呼叫Work類中的其它函式
    _current->Write_program(this);
}

void Work::Set_task_finished(bool finish)
{
    _finish = finish;
}

bool Work::Get_task_finished()
{
    return _finish;
}

int main()
{
    //緊急專案
    Work *emergencyProjects = new Work();
    //上班時間
    emergencyProjects->Set_hour(9);
    emergencyProjects->Write_program();
    emergencyProjects->Set_hour(10);
    emergencyProjects->Write_program();
    emergencyProjects->Set_hour(11);
    emergencyProjects->Write_program();
    emergencyProjects->Set_hour(12);
    emergencyProjects->Write_program();
    emergencyProjects->Set_hour(13);
    emergencyProjects->Write_program();
    emergencyProjects->Set_hour(14);
    emergencyProjects->Write_program();
    emergencyProjects->Set_hour(17);

    //任務沒有完成
    emergencyProjects->Set_task_finished(false);

    emergencyProjects->Write_program();
    emergencyProjects->Set_hour(19);
    emergencyProjects->Write_program();
    emergencyProjects->Set_hour(22);
    emergencyProjects->Write_program();

    //釋放資源
    delete emergencyProjects;

    return 0;
}

State模式的適用性(摘錄自《設計模式》):
1.一個物件的行為取決於他的狀態,並且它必須在執行時刻根據狀態改變他的行為.
2.一個操作中含有龐大的多分支的條件語句,且這些分支依賴與該物件的狀態.這個狀態常用一個或多個列舉常量表示.State模式將每個條件分支放入一個獨立的類中.這使得你可以根據物件自身的情況將物件的狀態作為一個物件,這以物件可以不依賴與其他物件而獨立變化.
State模式的優點(摘錄自《設計模式》):
1.它將與特定狀態相關的行為區域性化,並且將不同狀態的行為分割開來 State模式將所有與一個特定的狀態熱愛相關的行為都放入一個物件中.因為所有與狀態相關的程式碼都存在於某個State子類中,所以通過定義新的子類可以很容易的增加新的狀態和轉換.
2.它使得狀態轉換顯式化 當一個物件僅以內部資料值來定義當前狀態時,其狀態僅表現為對一些變數的複製,這不夠明確.為不同的狀態引入獨立的物件使得轉換變得更加的明確.而且State物件可以保證context不會發生內部狀態不一致的情況,因為從context角度看狀態轉換是原子的——–只需重新繫結一個變數(即context的State物件變數)而無需為多個變數賦值
3.State物件可以被共享 如果State物件沒有例項變數——-即它們表示的狀態完全以它們的型別來編碼——那麼各context物件可以共享一個State物件.當狀態以這種方式被共享時,它們必然是沒有內部狀態,只有行為的輕量級物件.