1.Iterator模式
Iterator.hpp:
#ifndef _ITERATOR_HPP
#define _ITERATOR_HPP
#include <vector>
struct 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
Main.cpp:
#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;
}
2.Template模式
Template.hpp:
#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
Main.cpp:
//作用:抽象顶层封装逻辑方法或者通用放,具体算法细节延迟到子类实现
//客户程序员只关心public的方法即本例子中的FrameMethod对外方法
//对外接口FrameMethod在顶层调用在该类中虚方法,封装了具体过程而
//不在关心子类方法
int main()
{
TopFrame *p1 = new Sub1;
TopFrame *p2 = new Sub2;
p1->FrameMethod();
p2->FrameMethod();
delete p1;
delete p2;
return 0;
}
3.Strategy模式
Strategy.hpp:
#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
Main.cpp:
//作用:重在策略,切换不同的方法行为
//对象行为相同,但实现不同,而且还有可能发送互相替换
//说白了就是对象之前切换然后调用行为方法
//典型例子为场景切换,或者有些游戏中的,武器切换
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;
}
4.State模式
State.hpp:
#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
Main.cpp:
//作用:从对象内部改变状态,控制对象行为避免外部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;
}
5.Observer模式
Observer.hpp:
#ifndef _OBSERVER_HPP
#define _OBSERVER_HPP
#include <set>
typedef unsigned int u32;
//以星际争霸2游戏中人族科技建筑为例
template <typename T>
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<u32> *pObserver )
{
mObservers.insert( pObserver );
}
virtual void DeleteObserver( IObserver<u32> *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<u32>* > 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
Main.cpp:
#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;
}
6.Command模式
Command.hpp:
#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
Main.cpp:
#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;
}
7.Memento模式
Memento.hpp:
#ifndef _MEMENTO_HPP
#define _MEMENTO_HPP
#include <memory>
template< 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
Main.cpp
#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;
}
未完待续...