#ifndef _ITERATOR_HPP #define _ITERATOR_HPP #includestruct Player { int mPID; }; class PlayerManager { public: PlayerManager() :mBeginIter( &mPlayers ) {} ~PlayerManager() {} struct Iterator { Iterator() { mref = nullptr; mIndex = 0; } Iterator( std::vector< Player* > *ref ) { mref = ref; mIndex = 0; } Iterator( const Iterator &other ) { mref = other.mref; mIndex = other.mIndex; } Iterator& operator = ( const Iterator &other ) { if( this == &other ) { return *this; } mIndex = other.mIndex; mref = other.mref; } Iterator& operator ++(int idx) { return operator ++(); } Iterator& operator ++() { ++mIndex; return *this; } bool operator !=( const Iterator &other ) { return mIndex != other.mIndex; } Player* operator *() { return (*mref)[ mIndex ]; } Player** operator ->() { return &(*mref)[ mIndex ]; } int mIndex; std::vector< Player* > *mref; }; void AddPlayer( Player *pPlayer ) { mPlayers.push_back( pPlayer ); mEndIter.mIndex = mPlayers.size(); } Iterator Begin() { return mBeginIter; } Iterator End() { return mEndIter; } private: std::vector< Player* > mPlayers; Iterator mBeginIter; Iterator mEndIter; }; #endif
#include "Iterator.hpp"
//作用:封裝對內部復雜聚合類的元素訪問,並且可以豐富擴展自定義功能,典型例子stl容器的iterator
//例子簡單實現了部分功能理解iterator模式
int main()
{
Player *p;
PlayerManager* ppm = new PlayerManager;
for( int i = 0; i < 3; ++i )
{
p = new Player;
p->mPID = i;
ppm->AddPlayer( p );
}
for( PlayerManager::Iterator i = ppm->Begin(); i != ppm->End(); ++i )
{
//迭代器訪問數據
int id = (*i)->mPID;
delete *i;
}
delete ppm;
return 0;
}
#ifndef _TEMPLATE_HPP
#define _TEMPLATE_HPP
class TopFrame
{
public:
TopFrame(){}
virtual ~TopFrame(){}
void FrameMethod()
{
//注意這裡,非虛方法封裝虛方法,凡是這種行為,即是template模式
//目的明確,FrameMethod對外,SubMethod1和SubMethod2在頂層對內
//當然有時候,我們無意中也會寫出設計模式來只不過我們不知道罷了
SubMethod1();
SubMethod2();
}
protected:
virtual void SubMethod1() = 0;
virtual void SubMethod2() = 0;
};
class Sub1 : public TopFrame
{
public:
Sub1(){}
~Sub1(){}
void SubMethod1(){}
void SubMethod2(){}
};
class Sub2 : public TopFrame
{
public:
Sub2(){}
~Sub2(){}
void SubMethod1(){}
void SubMethod2(){}
};
#endif
//作用:抽象頂層封裝邏輯方法或者通用放,具體算法細節延遲到子類實現
//客戶程序員只關心public的方法即本例子中的FrameMethod對外方法
//對外接口FrameMethod在頂層調用在該類中虛方法,封裝了具體過程而
//不在關心子類方法
int main()
{
TopFrame *p1 = new Sub1;
TopFrame *p2 = new Sub2;
p1->FrameMethod();
p2->FrameMethod();
delete p1;
delete p2;
return 0;
}
#ifndef _STRATEGY_HPP
#define _STRATEGY_HPP
class Scene
{
public:
virtual ~Scene(){}
virtual void Init() = 0;
virtual void Update() = 0;
virtual void Render() = 0;
virtual void Destroy() = 0;
};
class MenuScene : public Scene
{
public:
MenuScene(){}
~MenuScene(){}
void Init(){}
void Update(){}
void Render(){}
void Destroy(){}
};
class LoadingScene : public Scene
{
public:
LoadingScene(){}
~LoadingScene(){}
void Init(){}
void Update(){}
void Render(){}
void Destroy(){}
};
class GameScene : public Scene
{
public:
GameScene(){}
~GameScene(){}
void Init(){}
void Update(){}
void Render(){}
void Destroy(){}
};
class App
{
public:
App()
{
mp = nullptr;
}
~App()
{
if( nullptr != mp )
{
delete mp;
}
}
void SwitchScene( Scene *p )
{
if(mp == p)
{
return;
}
if( nullptr != mp )
{
mp->Destroy();
}
mp = p;
mp->Init();
}
void Run()
{
if(nullptr == mp)
{
return;
}
mp->Update();
mp->Render();
}
private:
Scene *mp;
};
#endif
//作用:重在策略,切換不同的方法行為
//對象行為相同,但實現不同,而且還有可能發送互相替換
//說白了就是對象之前切換然後調用行為方法
//典型例子為場景切換,或者有些游戲中的,武器切換
int main()
{
Scene *p1 = new MenuScene;
Scene *p2 = new LoadingScene;
Scene *p3 = new GameScene;
App *pa = new App;//簡單模擬場景管理
//切換到菜單場景
pa->SwitchScene( p1 );
//調用菜單場景邏輯和渲染( 這裡只是簡單模擬場景切換 )
pa->Run();
//切換到資源加載場景
pa->SwitchScene( p2 );
pa->Run();
//切換到游戲場景
pa->SwitchScene( p3 );
pa->Run();
delete pa;
delete p3;
delete p2;
delete p1;
return 0;
}
#ifndef _STATE_HPP
#define _STATE_HPP
class M16_Rifle;
//抽象狀態
class M16_State
{
protected:
M16_State(){}
public:
virtual ~M16_State(){}
//開火時的音效
virtual void FireAudio() = 0;
//調整影響槍的火力
virtual void AdjustPower( M16_Rifle *pM16 ) = 0;
};
class M16_MufflerState : public M16_State
{
public:
M16_MufflerState(){}
~M16_MufflerState(){}
private:
void FireAudio()
{
//播放消音開火音效
}
void AdjustPower( M16_Rifle *pM16 )
{
//消音狀態下火力減少
//pM16->mPower -= 10;
}
};
class M16_NormalState : public M16_State
{
public:
M16_NormalState(){}
~M16_NormalState(){}
private:
void FireAudio()
{
//播放非消音開火音效
}
void AdjustPower( M16_Rifle *pM16 )
{
//非消音狀態下火力回復
//pM16->mPower += 10;
}
};
class M16_Rifle
{
public:
friend class M16_MufflerState;
friend class M16_NormalState;
M16_Rifle()
{
mpMullfer = new M16_MufflerState;
mpNormal = new M16_NormalState;
mpCurr = mpNormal;
mPower = 50;
}
~M16_Rifle()
{
delete mpMullfer;
delete mpNormal;
}
void Fire()
{
mpCurr->FireAudio();
//...
}
//消音和不消音來回切換
void SwitchFireMode()
{
mpCurr = mpCurr == mpNormal ? mpMullfer : mpNormal;
mpCurr->AdjustPower( this );
}
private:
M16_State *mpMullfer;
M16_State *mpNormal;
M16_State *mpCurr;
int mPower;
};
#endif
//作用:從對象內部改變狀態,控制對象行為避免外部switch if else 嵌套結構
//CS游戲中警察M-16這種自動步槍就有兩種狀態
//普通狀態和消音器狀態
//有人說用bool值就行了,如果是3種以上且有嵌套的復雜狀態呢?
int main()
{
M16_Rifle *pM16 = new M16_Rifle;
//默認非消音
pM16->Fire();
//切換消音
pM16->SwitchFireMode();
pM16->Fire();
//切換非消音
pM16->SwitchFireMode();
pM16->Fire();
delete pM16;
return 0;
}
#ifndef _OBSERVER_HPP #define _OBSERVER_HPP #includetypedef unsigned int u32; //以星際爭霸2游戲中人族科技建築為例 template class IObserver; //被觀察者 template< typename T > class IObservable { public: IObservable(){} virtual ~IObservable(){} virtual void AddObserver( IObserver< T > *pObserver ) = 0; virtual void DeleteObserver( IObserver< T > *pObserver ) = 0; virtual void NotifyObservers( T context ) = 0; }; //觀察者 template< typename T > class IObserver { public: IObserver(){} virtual ~IObserver(){} virtual void Update( T context ) = 0; }; //晶礦 class Crystal : public IObservable< u32 > { public: Crystal(){} ~Crystal(){} virtual void AddObserver( IObserver *pObserver ) { mObservers.insert( pObserver ); } virtual void DeleteObserver( IObserver *pObserver ) { mObservers.erase( pObserver ); } virtual void NotifyObservers( u32 context ) { for( auto i = mObservers.begin(); i != mObservers.end(); ++i ) { (*i)->Update( context ); } } private: std::set< IObserver * > mObservers; }; //重工廠 class Factory : public IObserver< u32 > { public: void Update( u32 context ) { if( context > 200 ) { //可建造重工廠 } } }; //兵營 class Barracks : public IObserver< u32 > { public: void Update( u32 content ) { if( content > 150 ) { //可建造兵營 } } }; #endif
#include "Observer.hpp"
//作用:被觀察者可以注冊可以觀察他的觀察者,被觀察者出發相應的事件或者狀態
//觀察者會收到相應的通知數據,根據數據做出不同的處理
//這個例子可能寫的比較特殊理解這種思想即可
int main()
{
//晶礦
Crystal *pCrystal = new Crystal;
//重工
Factory *pF = new Factory;
//兵營
Barracks *pB = new Barracks;
pCrystal->AddObserver( pF );
pCrystal->AddObserver( pB );
u32 Count = 1000;
//采礦1000
pCrystal->NotifyObservers( Count );
delete pB;
delete pF;
delete pCrystal;
return 0;
}
#ifndef _COMMAND_HPP
#define _COMMAND_HPP
//Command模式使用的范圍就太多了
//例如星際爭霸中人族SCV的控制面板( 移動、攻擊、巡邏、采礦、停止... )
class Command
{
public:
Command(){}
virtual ~Command(){}
virtual void Execute() = 0;
};
class SCV
{
public:
SCV(){}
~SCV(){}
void Move( int x, int y ){}
void Attack( int x, int y ){}
void Round( int x, int y ){}
void Mining( int x, int y ){}
void Stop(){}
};
//將行為進行封裝
class MoveCommand : public Command
{
public:
MoveCommand(){}
~MoveCommand(){}
MoveCommand( SCV *p, int x, int y )
{
mp = p;
mx = x;
my = y;
}
void Execute()
{
mp->Move( mx, my );
}
private:
SCV *mp;
int mx;
int my;
};
class AttackCommand : public Command
{
public:
AttackCommand(){}
~AttackCommand(){}
AttackCommand( SCV *p, int x, int y )
{
mp = p;
mx = x;
my = y;
}
void Execute()
{
mp->Attack( mx, my );
}
private:
SCV *mp;
int mx;
int my;
};
class RoundCommand : public Command
{
public:
RoundCommand(){}
~RoundCommand(){}
RoundCommand( SCV *p, int x, int y )
{
mp = p;
mx = x;
my = y;
}
void Execute()
{
mp->Round( mx, my );
}
private:
SCV *mp;
int mx;
int my;
};
class MiningCommand : public Command
{
public:
MiningCommand(){}
~MiningCommand(){}
MiningCommand( SCV *p, int x, int y )
{
mp = p;
mx = x;
my = y;
}
void Execute()
{
mp->Mining( mx, my );
}
private:
SCV *mp;
int mx;
int my;
};
class StopCommand : public Command
{
public:
StopCommand(){}
~StopCommand(){}
StopCommand( SCV *p )
{
mp = p;
}
void Execute()
{
mp->Stop();
}
private:
SCV *mp;
};
//命令者只知道接口,具體如何實現他不知道
class Commander
{
public:
Commander( Command *pCmdMove, Command *pCmdAttack, Command *pCmdRound, Command *pCmdMining, Command *pCmdStop )
{
mpCmdMove = pCmdMove;
mpCmdAttack = pCmdAttack;
mpCmdRound = pCmdRound;
mpCmdMining = pCmdMining;
mpCmdStop = pCmdStop;
}
~Commander()
{}
void Move()
{
mpCmdMove->Execute();
}
void Attack()
{
mpCmdAttack->Execute();
}
void Round()
{
mpCmdRound->Execute();
}
void Mining()
{
mpCmdMining->Execute();
}
void Stop()
{
mpCmdStop->Execute();
}
private:
Command *mpCmdMove;
Command *mpCmdAttack;
Command *mpCmdRound;
Command *mpCmdMining;
Command *mpCmdStop;
};
#endif
#include "Command.hpp"
//作用:將高層命令與行為解耦,特別適合對象行為固定的情況下非常方便
//某些情況下特別適合undo 和 redo 因為Command模式會儲存行為的數據
//將他們放入棧內....push pop...本例不討論
//例子只是讓人更好理解而已,寫的不是太恰當
//不想舉一些跟程序無關的例子
int main()
{
SCV *pScv = new SCV;
//移動命令
MoveCommand *pCmdMove = new MoveCommand( pScv, 0, 0 );
//攻擊命令
AttackCommand *pCmdAtt = new AttackCommand( pScv, 0, 0 );
//巡邏命令
RoundCommand *pCmdRound = new RoundCommand( pScv, 0, 0 );
//采礦命令
MiningCommand *pCmdMining = new MiningCommand( pScv, 0, 0 );
//停止命令
StopCommand *pCmdStop = new StopCommand( pScv );
//指揮官面板
Commander *pCmder = new Commander( pCmdMove, pCmdAtt, pCmdRound, pCmdMining, pCmdStop );
pCmder->Move();
pCmder->Attack();
pCmder->Round();
pCmder->Mining();
pCmder->Stop();
delete pCmder;
delete pCmdStop;
delete pCmdMining;
delete pCmdRound;
delete pCmdAtt;
delete pCmdMove;
delete pScv;
return 0;
}
#ifndef _MEMENTO_HPP #define _MEMENTO_HPP #includetemplate< typename T > class Memento { public: Memento( T *pt ) { mpt = new T( *pt ); } ~Memento() { delete mpt; mpt = nullptr; } T* GetData() { return mpt; } private: T *mpt; }; class Setting { public: Setting() { mData1 = mData2 = mData3 = 0; mp = new char[ 32 ]; strcpy_s( mp, 32, "default" ); } Setting( const Setting &other ) { mData1 = other.mData1; mData2 = other.mData2; mData3 = other.mData3; mp = new char[ 32 ]; strcpy_s( mp, 32, other.mp ); } ~Setting() { delete mp; mp = nullptr; } Memento< Setting >* CreateRestore() { return new Memento< Setting >( this ); } void Restore( Memento< Setting > *p ) { auto px = p->GetData(); mData1 = px->mData1; mData2 = px->mData2; mData3 = px->mData3; strcpy_s( mp, 32, px->mp ); } void SetData( int d1, int d2, int d3, char *p ) { mData1 = d1; mData2 = d2; mData3 = d3; strcpy_s( mp, 32, p ); } void print() { printf( "%d\n", mData1 ); printf( "%d\n", mData2 ); printf( "%d\n", mData3 ); printf( "%s\n\n", mp ); } private: int mData1; int mData2; int mData3; char *mp; }; #endif
#include "Memento.hpp"
//作用:記錄對象數據的快照,在後續需要的情況下根據快照重新還原對象數據
//例如我們常用的一些設置面板,參數繁多,很容易設置錯誤,當設置錯誤時
//通過一種手段還原到最初的默認數據
int main()
{
auto *pSet = new Setting;
//打印一下默認的設置數據
pSet->print();
//記錄一下默認設置數據還原點
auto *pDefPoint = pSet->CreateRestore();
//設置新設置數據
pSet->SetData( 102, 103, 32, "new data1" );
pSet->print();
//創建記錄新的還原點
auto *pNewPoint = pSet->CreateRestore();
//設置新的設置數據
pSet->SetData( 32, 1, 3, "new data2" );
pSet->print();
//創建新的還原點2
auto *pNewPoint2 = pSet->CreateRestore();
//我後悔了想要恢復的默認數據
pSet->Restore( pDefPoint );
pSet->print();
//我後悔了想要恢復到第一次設置新數據哪裡
pSet->Restore( pNewPoint );
pSet->print();
//我後悔了還是恢復到最後一次的吧
pSet->Restore( pNewPoint2 );
pSet->print();
delete pNewPoint2;
delete pNewPoint;
delete pDefPoint;
delete pSet;
return 0;
}

未完待續...