首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> C# 入門

用設計模式固化你的 C# 程式(六-2):C++ State 實作細節與記憶體管理

     編輯:C# 入門

C++ State 模式完整實作細節

本文補充 C++ 版本的完整類別定義與記憶體管理考量,作為跨語言設計模式實作的參考。

state.h - 完整類別宣告


#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

state.cpp - 關鍵實作細節


#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;
}

C++ 記憶體管理關鍵點

  1. 單例記憶體洩漏風險:靜態 new 的單例實例在程式結束前不會自動釋放,需手動 delete 或使用 std::unique_ptr 管理。
  2. 虛擬解構子:State 基底類別應宣告 virtual ~State() = default; 確保正確解構衍生類別。
  3. 擁有權語意:VendingMachine 持有 State* 但不擁有單例,不應在解構子刪除 _state。
  4. 現代 C++ 改良:建議使用 std::unique_ptr<State> 管理 Context 擁有的狀態,單例改用 static State& Instance() 回傳參考。

跨語言設計模式實作比較

面向C#C++ (傳統)C++ (現代 C++11/14/17)
單例實作static readonly / Lazy<T>static 指標 + 手動 new/deletestatic 區域變數 (Meyer's Singleton) / unique_ptr
多型呼叫虛擬方法 / 介面virtual 函式virtual + override + final
記憶體管理GC 自動手動 new/deleteRAII + 智慧指標 (unique_ptr/shared_ptr)
介面定義interface 關鍵字純虛擬類別純虛擬類別 + concepts (C++20)
委派/回呼delegate / Action / Func函式指標 / std::functionstd::function / lambda / 概念

設計模式學習心法

  1. 模式是詞彙而非法規:提供共同溝通語言,而非強制規範。
  2. 理解權衡:每個模式都有適用場景與代價(複雜度、效能、耦合)。
  3. 重構導向:在程式碼出現「異味」時重構引入模式,而非一開始就過度設計。
  4. 跨語言迁移:掌握模式本質,可在任何支援物件導向的語言中實作。

結語

本系列從 Singleton 到 State,展示了五大經典設計模式在 C# 與 C++ 中的實作精髓。C# 的語言特性(GC、介面、委派、泛型、模式比對)讓模式實作更簡潔、安全、富表達力。希望讀者能將這些模式內化為設計直覺,在實務專案中靈活運用,打造高品質軟體。

—— 設計模式系列完整結束 ——

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved