介紹
? ? ? ? 狀態(tài)模式允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為,對(duì)象看起來(lái)似乎修改了它的類。其別名為狀態(tài)對(duì)象,狀態(tài)模式是一種對(duì)象行為模式。
實(shí)現(xiàn)
myclass.h
//
// Created by yuwp on 2024/1/12.
//
#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H
#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>
#include <memory>
class State { // 抽象狀態(tài)類
public:
virtual void handle() = 0;
};
class Context { // 環(huán)境類
public:
Context();
void setState(const std::shared_ptr<State> &state);
void request(int num);
void changeState();
private:
std::shared_ptr<State> m_state;
int m_value;
};
class ConcreteStateA : public State { // 具體狀態(tài)類A
public:
void handle() override;
};
class ConcreteStateB : public State { // 具體狀態(tài)類B
public:
void handle() override;
};
#endif //DESIGNPATTERNS_MYCLASS_H
myclass.cpp
//
// Created by yuwp on 2024/1/12.
//
#include "myclass.h"
#include <thread>
#include <unistd.h>
#include <sstream>
Context::Context() {
m_value = 0;
m_state.reset(new ConcreteStateA());
}
void Context::setState(const std::shared_ptr<State> &state) {
m_state = state;
}
void Context::request(int num) {
int tmp = m_value;
m_value += num;
if ((tmp >= 0 && m_value < 0) || (tmp < 0 && m_value >= 0)) {
changeState();
}
m_state->handle();
}
void Context::changeState() {
std::cout << "切換狀態(tài)" << std::endl;
if (m_value >= 0) {
m_state.reset(new ConcreteStateA());
} else {
m_state.reset(new ConcreteStateB());
}
}
void ConcreteStateA::handle() {
std::cout << "ConcreteStateA::handle()" << std::endl;
}
void ConcreteStateB::handle() {
std::cout << "ConcreteStateB::handle()" << std::endl;
}
main.cpp
#include <iostream>
#include <mutex>
#include "myclass.h"
int main() {
Context *context = new Context;
context->request(0);
std::cout << "-------------------" << std::endl;
context->request(-10);
std::cout << "-------------------" << std::endl;
context->request(20);
return 0;
}
總結(jié)
優(yōu)點(diǎn)
? ? ? ? 1.?封裝了狀態(tài)的轉(zhuǎn)換規(guī)則。在狀態(tài)模式中可以將狀態(tài)的轉(zhuǎn)換代碼封裝在環(huán)境類或者具體狀態(tài)類中,對(duì)狀態(tài)轉(zhuǎn)換代碼進(jìn)行集中管理,而不是分散在一個(gè)個(gè)業(yè)務(wù)方法中。
? ? ? ? 2.?將所有與某個(gè)狀態(tài)有關(guān)的行為放到一個(gè)類中,只需要注入一個(gè)不同的狀態(tài)對(duì)象即可使環(huán)境對(duì)象擁有不同的行為。
? ? ? ? 3.?允許狀態(tài)轉(zhuǎn)換邏輯與狀態(tài)對(duì)象合成一體,而不是提供一個(gè)巨大的條件語(yǔ)句塊。狀態(tài)模式可以避免使用龐大的條件語(yǔ)句來(lái)將業(yè)務(wù)方法和狀態(tài)轉(zhuǎn)換代碼交織在一起。
? ? ? ? 4.?可以讓多個(gè)環(huán)境對(duì)象共享一個(gè)狀態(tài)對(duì)象,從而減少系統(tǒng)中對(duì)象的個(gè)數(shù)。
缺點(diǎn)
? ? ? ? 1.?狀態(tài)模式的使用必然會(huì)增加系統(tǒng)中類和對(duì)象的個(gè)數(shù),導(dǎo)致系統(tǒng)運(yùn)行開(kāi)銷增大。
? ? ? ? 2.?狀態(tài)模式的程序結(jié)構(gòu)與實(shí)現(xiàn)都較為復(fù)雜,如果使用不當(dāng)將導(dǎo)致程序結(jié)構(gòu)和代碼的混亂,增加系統(tǒng)設(shè)計(jì)的難度。
? ? ? ? 3.?狀態(tài)模式對(duì)開(kāi)閉原則的支持并不太好。增加新的狀態(tài)類需要修改那些負(fù)責(zé)狀態(tài)轉(zhuǎn)換的源代碼,否則無(wú)法轉(zhuǎn)換到新增狀態(tài);而且修改某個(gè)狀態(tài)類的行為也需修改對(duì)應(yīng)類的源代碼。
適用場(chǎng)景
? ? ? ? 1.?對(duì)象的行為依賴于它的狀態(tài)(例如某些屬性值),狀態(tài)的改變將導(dǎo)致行為的變化。
? ? ? ? 2.?在代碼中包含大量與對(duì)象狀態(tài)有關(guān)的條件語(yǔ)句。這些條件語(yǔ)句的出現(xiàn),會(huì)導(dǎo)致代碼的可維護(hù)性和靈活性變差,不能方便地增加和刪除狀態(tài),并且導(dǎo)致客戶類與類庫(kù)之間的耦合增強(qiáng)。
練習(xí)
myclass.h
//
// Created by yuwp on 2024/1/12.
//
#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H
#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>
#include <memory>
class Level { // 抽象狀態(tài)類
public:
virtual void play() = 0;
virtual void doubleScore();
virtual void changeCards();
virtual void peekCards();
};
class CardsGame {
public:
CardsGame();
~CardsGame();
void play(int score); // 模擬玩游戲得分
void doubleScore();
void changeCards();
void peekCards();
private:
Level *m_level; // 當(dāng)前等級(jí)
Level *m_primary; // 入門級(jí)
Level *m_secondary; // 熟練級(jí)
Level *m_professional; // 高手級(jí)
Level *m_final; // 骨灰級(jí)
int m_score; // 得分
};
class PrimaryLevel : public Level {
public:
void play() override;
void doubleScore() override;
void changeCards() override;
void peekCards() override;
};
class SecondaryLevel : public Level {
public:
void play() override;
void changeCards() override;
void peekCards() override;
};
class ProfessionalLevel : public Level {
public:
void play() override;
void peekCards() override;
};
class FinalLevel : public Level {
public:
void play() override;
};
#endif //DESIGNPATTERNS_MYCLASS_H
myclass.cpp文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-824368.html
//
// Created by yuwp on 2024/1/12.
//
#include "myclass.h"
#include <thread>
#include <unistd.h>
#include <sstream>
void Level::doubleScore() {
std::cout << "勝利積分加倍" << std::endl;
}
void Level::changeCards() {
std::cout << "換牌" << std::endl;
}
void Level::peekCards() {
std::cout << "偷看他人的牌" << std::endl;
}
CardsGame::CardsGame() {
m_primary = new PrimaryLevel();
m_secondary = new SecondaryLevel();
m_professional = new ProfessionalLevel();
m_final = new FinalLevel();
m_level = m_primary;
m_score = 0;
}
CardsGame::~CardsGame() {
if (m_primary) {
delete m_primary;
}
if (m_secondary) {
delete m_secondary;
}
if (m_professional) {
delete m_professional;
}
if (m_final) {
delete m_final;
}
}
void CardsGame::play(int score) {
m_level->play();
m_score += score;
if (m_score < 100) {
if (m_level != m_primary) {
std::cout << "切換到入門級(jí)" << std::endl;
m_level = m_primary;
}
} else if (m_score < 500) {
if (m_level != m_secondary) {
std::cout << "切換到熟練級(jí)" << std::endl;
m_level = m_secondary;
}
} else if (m_score < 1000) {
if (m_level != m_professional) {
std::cout << "切換到高手級(jí)" << std::endl;
m_level = m_professional;
}
} else {
if (m_level != m_final) {
std::cout << "切換到骨灰級(jí)" << std::endl;
m_level = m_final;
}
}
}
void CardsGame::changeCards() {
m_level->changeCards();
}
void CardsGame::doubleScore() {
m_level->doubleScore();
}
void CardsGame::peekCards() {
m_level->peekCards();
}
void PrimaryLevel::play() {
std::cout << "入門級(jí)游戲開(kāi)始" << std::endl;
}
void PrimaryLevel::doubleScore() {
std::cout << "入門級(jí)不支持游戲勝利積分加倍功能" << std::endl;
}
void PrimaryLevel::changeCards() {
std::cout << "入門級(jí)不支持換牌功能" << std::endl;
}
void PrimaryLevel::peekCards() {
std::cout << "入門級(jí)不支持偷看他人的牌功能" << std::endl;
}
void SecondaryLevel::play() {
std::cout << "熟練級(jí)游戲開(kāi)始" << std::endl;
}
void SecondaryLevel::changeCards() {
std::cout << "熟練級(jí)不支持換牌功能" << std::endl;
}
void SecondaryLevel::peekCards() {
std::cout << "熟練級(jí)不支持偷看他人的牌功能" << std::endl;
}
void ProfessionalLevel::play() {
std::cout << "高手級(jí)游戲開(kāi)始" << std::endl;
}
void ProfessionalLevel::peekCards() {
std::cout << "高手級(jí)不支持偷看他人的牌功能" << std::endl;
}
void FinalLevel::play() {
std::cout << "骨灰級(jí)游戲開(kāi)始" << std::endl;
}
main.cpp文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-824368.html
#include <iostream>
#include <mutex>
#include "myclass.h"
int main() {
CardsGame *cardsGame = new CardsGame();
cardsGame->doubleScore();
cardsGame->changeCards();
cardsGame->peekCards();
cardsGame->play(200);
std::cout << "------------------------" << std::endl;
cardsGame->doubleScore();
cardsGame->changeCards();
cardsGame->peekCards();
cardsGame->play(500);
std::cout << "------------------------" << std::endl;
cardsGame->doubleScore();
cardsGame->changeCards();
cardsGame->peekCards();
cardsGame->play(500);
std::cout << "------------------------" << std::endl;
cardsGame->doubleScore();
cardsGame->changeCards();
cardsGame->peekCards();
cardsGame->play(0);
delete cardsGame;
return 0;
}
到了這里,關(guān)于《設(shè)計(jì)模式的藝術(shù)》筆記 - 狀態(tài)模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!