本文補充 C++ 版本的完整類別定義與記憶體管理考量,作為跨語言設計模式實作的參考。
#ifndef STATE_H
#define STATE_H
class VendingMachine;
class State {
public:
virtual void AddNickel(VendingMachine* vm) {}
virtual void AddDime(VendingMachine* vm) {}
virtual void AddQuarter(VendingMachine* vm) {}
protected:
virtual void ChangeState(VendingMachine* vm, State* s);
};
class VendingMachine {
State* _state;
public:
VendingMachine();
void ChangeState(State* to);
void Vend();
void AddNickel();
void AddDime();
void AddQuarter();
};
// 所有狀態類別宣告
class StartState : public State {
static State* _instance;
StartState() {}
public:
static State* Instance();
void AddNickel(VendingMachine* vm) override;
void AddDime(VendingMachine* vm) override;
void AddQuarter(VendingMachine* vm) override;
};
class FiveState : public State {
static State* _instance;
FiveState() {}
public:
static State* Instance();
void AddNickel(VendingMachine* vm) override;
void AddDime(VendingMachine* vm) override;
void AddQuarter(VendingMachine* vm) override;
};
class TenState : public State {
static State* _instance;
TenState() {}
public:
static State* Instance();
void AddNickel(VendingMachine* vm) override;
void AddDime(VendingMachine* vm) override;
void AddQuarter(VendingMachine* vm) override;
};
class FifteenState : public State {
static State* _instance;
FifteenState() {}
public:
static State* Instance();
void AddNickel(VendingMachine* vm) override;
void AddDime(VendingMachine* vm) override;
void AddQuarter(VendingMachine* vm) override;
};
class TwentyState : public State {
static State* _instance;
TwentyState() {}
public:
static State* Instance();
void AddNickel(VendingMachine* vm) override;
void AddDime(VendingMachine* vm) override;
void AddQuarter(VendingMachine* vm) override;
};
#endif
#include "state.h"
#include
using namespace std;
void State::ChangeState(VendingMachine* vm, State* s) {
vm->ChangeState(s);
}
VendingMachine::VendingMachine() {
cout << "The Vending Machine is now online: product costs 25c" << endl;
_state = StartState::Instance();
}
void VendingMachine::ChangeState(State* to) { _state = to; }
void VendingMachine::Vend() { cout << "Dispensing product...Thank you!" << endl; }
void VendingMachine::AddNickel() { _state->AddNickel(this); }
void VendingMachine::AddDime() { _state->AddDime(this); }
void VendingMachine::AddQuarter() { _state->AddQuarter(this); }
// 靜態單例實例定義與初始化
State* StartState::_instance = new StartState();
State* StartState::Instance() {
cout << "Credit: 0c" << endl;
return _instance;
}
void StartState::AddNickel(VendingMachine* vm) { ChangeState(vm, FiveState::Instance()); }
void StartState::AddDime(VendingMachine* vm) { ChangeState(vm, TenState::Instance()); }
void StartState::AddQuarter(VendingMachine* vm) { vm->Vend(); }
State* FiveState::_instance = new FiveState();
State* FiveState::Instance() {
cout << "Credit: 5c" << endl;
return _instance;
}
void FiveState::AddNickel(VendingMachine* vm) { ChangeState(vm, TenState::Instance()); }
void FiveState::AddDime(VendingMachine* vm) { ChangeState(vm, FifteenState::Instance()); }
void FiveState::AddQuarter(VendingMachine* vm) {
vm->Vend();
ChangeState(vm, StartState::Instance()); // 不找零 :-)
}
State* TenState::_instance = new TenState();
State* TenState::Instance() {
cout << "Credit: 10c" << endl;
return _instance;
}
void TenState::AddNickel(VendingMachine* vm) { ChangeState(vm, FifteenState::Instance()); }
void TenState::AddDime(VendingMachine* vm) { ChangeState(vm, TwentyState::Instance()); }
void TenState::AddQuarter(VendingMachine* vm) {
vm->Vend();
ChangeState(vm, StartState::Instance());
}
State* FifteenState::_instance = new FifteenState();
State* FifteenState::Instance() {
cout << "Credit: 15c" << endl;
return _instance;
}
void FifteenState::AddNickel(VendingMachine* vm) { ChangeState(vm, TwentyState::Instance()); }
void FifteenState::AddDime(VendingMachine* vm) {
vm->Vend();
ChangeState(vm, StartState::Instance());
}
void FifteenState::AddQuarter(VendingMachine* vm) {
vm->Vend();
ChangeState(vm, StartState::Instance());
}
State* TwentyState::_instance = new TwentyState();
State* TwentyState::Instance() {
cout << "Credit: 20c" << endl;
return _instance;
}
void TwentyState::AddNickel(VendingMachine* vm) {
vm->Vend();
ChangeState(vm, StartState::Instance());
}
void TwentyState::AddDime(VendingMachine* vm) {
vm->Vend();
ChangeState(vm, StartState::Instance());
}
void TwentyState::AddQuarter(VendingMachine* vm) {
vm->Vend();
ChangeState(vm, StartState::Instance());
}
int main() {
int coin = 0;
VendingMachine* vm = new VendingMachine();
for (int i = 0; i < 10; ++i) { // 限制迴圈次數避免記憶體洩漏示範
cout << "Insert a coin (5, 10, 25): ";
cin >> coin;
switch (coin) {
case 5: vm->AddNickel(); break;
case 10: vm->AddDime(); break;
case 25: vm->AddQuarter(); break;
default: break;
}
}
// 手動釋放單例記憶體 (教學示範)
delete StartState::Instance();
delete FiveState::Instance();
delete TenState::Instance();
delete FifteenState::Instance();
delete TwentyState::Instance();
delete vm;
return 0;
}
new 的單例實例在程式結束前不會自動釋放,需手動 delete 或使用 std::unique_ptr 管理。State 基底類別應宣告 virtual ~State() = default; 確保正確解構衍生類別。VendingMachine 持有 State* 但不擁有單例,不應在解構子刪除 _state。std::unique_ptr<State> 管理 Context 擁有的狀態,單例改用 static State& Instance() 回傳參考。| 面向 | C# | C++ (傳統) | C++ (現代 C++11/14/17) |
|---|---|---|---|
| 單例實作 | static readonly / Lazy<T> | static 指標 + 手動 new/delete | static 區域變數 (Meyer's Singleton) / unique_ptr |
| 多型呼叫 | 虛擬方法 / 介面 | virtual 函式 | virtual + override + final |
| 記憶體管理 | GC 自動 | 手動 new/delete | RAII + 智慧指標 (unique_ptr/shared_ptr) |
| 介面定義 | interface 關鍵字 | 純虛擬類別 | 純虛擬類別 + concepts (C++20) |
| 委派/回呼 | delegate / Action / Func | 函式指標 / std::function | std::function / lambda / 概念 |
本系列從 Singleton 到 State,展示了五大經典設計模式在 C# 與 C++ 中的實作精髓。C# 的語言特性(GC、介面、委派、泛型、模式比對)讓模式實作更簡潔、安全、富表達力。希望讀者能將這些模式內化為設計直覺,在實務專案中靈活運用,打造高品質軟體。
—— 設計模式系列完整結束 ——