Wzorce projektowe
stan
[wzorzec projektowy] Automatycznie kontroluje wewnętrzne zachowanie obiektu, nadając mu odpowiedni stan i funkcjonalność.Budowa wzorca projektowego
class IState
{
public:
virtual void metoda1() = 0;
virtual void metoda2( int argument ) = 0;
virtual int metoda3( double argument ) = 0;
};
class CObject_State1
: public IState
{
};
class CObject_State2
: public IState
{
};
class CObject_State3
: public IState
{
};
class CObject
{
private:
IState * m_pState;
public:
void uruchom_metode1();
void uruchom_metode2( int argument );
int uruchom_metode3( double argument );
};
Opis szczegółowy
Stan
(ang. state) - wzorzec projektowy, który ma na celu ułatwić rozbudowę obiektu o nowe stany. Wraz ze zmianą stanu następuje zmiana zachowania obiektu.
Wszystkie stany dla danego obiektu muszą posiadać wspólny interfejs. Stany są obiektami tymczasowymi. Dane, które mają być trwałe muszą zostać zapisane do obiektu głównego. Dane tymczasowe powinny być trzymane w stanie do czasu uzyskania kompletnego zestawu danych, a następnie przekazane do obiektu głównego.
Dodatkowe informacje
strategia jest wzorcem projektowym o takiej samej konstrukcji jak
state. Istnieje jednak między nimi istotna różnica w zasadzie działania. Wzorzec projektowy
state powinien posiadać następujące własności:
Przykład - szkielet klasy głównej
class CObject
{
private:
IState * m_pState;
public:
void selectPen()
{
m_pState = new CPen( this );
}
void selectLine()
{
m_pState = new CLine( this );
}
void selectRect()
{
m_pState = new CRect( this );
}
void onMouseDown( const CPoint & pos )
{
if( m_pState )
m_pState->onMouseDown( pos );
}
void onMouseUp( const CPoint & pos )
{
if( m_pState )
m_pState->onMouseUp( pos );
}
void onMouseMove( const CPoint & pos )
{
if( m_pState )
m_pState->onMouseMove( pos );
}
};
Przykład - kompletna aplikacja
#include <cstdio>
#include <cctype>
#include <sstream>
#include <list>
#include <algorithm>
class CTelevisor;
class TTelevisor_State
{
private:
CTelevisor * const m_pTv;
protected:
CTelevisor * const getParent();
public:
TTelevisor_State( CTelevisor * const pTv );
virtual ~TTelevisor_State();
virtual void putInput( char c ) = 0;
};
class CTelevisor
{
private:
friend class TTelevisor_State;
void setState( TTelevisor_State * pState );
TTelevisor_State * m_pState;
typedef std::list < TTelevisor_State *> StatesT;
StatesT m_toDelete;
void eraseOldStates();
static void eraseState( TTelevisor_State * pState );
protected:
friend class CTVState_Idle;
friend class CTVState_PowerOnOff;
friend class CTVState_PickChannel;
bool m_bIsTurnedOn;
int m_iChannel;
public:
CTelevisor();
~CTelevisor();
void recvSignal( char c );
void powerOn();
void powerOff();
};
class CTVState_PowerOnOff
: public TTelevisor_State
{
public:
CTVState_PowerOnOff( CTelevisor * const pTv );
virtual void putInput( char c );
};
class CTVState_Idle
: public TTelevisor_State
{
public:
CTVState_Idle( CTelevisor * const pTv );
virtual void putInput( char c );
};
class CTVState_PickChannel
: public TTelevisor_State
{
private:
std::stringstream m_sNewChannel;
public:
CTVState_PickChannel( CTelevisor * const pTv );
virtual void putInput( char c );
};
int main()
{
CTelevisor tv;
tv.powerOn();
tv.recvSignal( '1' );
tv.recvSignal( '0' );
tv.powerOff();
tv.powerOn();
tv.recvSignal( '0' );
tv.recvSignal( '7' );
tv.powerOff();
return 0;
}
CTelevisor * const TTelevisor_State::getParent()
{
return m_pTv;
}
TTelevisor_State::TTelevisor_State( CTelevisor * const pTv )
: m_pTv( pTv )
{
}
TTelevisor_State::~TTelevisor_State()
{
}
void CTelevisor::setState( TTelevisor_State * pState )
{
if( m_pState )
m_toDelete.push_back( m_pState );
m_pState = pState;
}
CTelevisor::CTelevisor()
: m_pState( NULL )
, m_bIsTurnedOn( false )
, m_iChannel( 1 )
{
}
CTelevisor::~CTelevisor()
{
eraseOldStates();
}
void CTelevisor::recvSignal( char c )
{
if( m_pState )
m_pState->putInput( c );
eraseOldStates();
}
void CTelevisor::powerOn()
{
printf( "powerOn()\n" );
CTVState_PowerOnOff * pPower = new CTVState_PowerOnOff( this );
setState( pPower );
pPower->putInput( '*' );
eraseOldStates();
}
void CTelevisor::powerOff()
{
printf( "powerOff()\n" );
CTVState_PowerOnOff * pPower = new CTVState_PowerOnOff( this );
setState( pPower );
pPower->putInput( '*' );
eraseOldStates();
}
void CTelevisor::eraseOldStates()
{
std::for_each( m_toDelete.begin(), m_toDelete.end(), eraseState );
m_toDelete.clear();
}
void CTelevisor::eraseState( TTelevisor_State * pState )
{
delete pState;
}
CTVState_PowerOnOff::CTVState_PowerOnOff( CTelevisor * const pTv )
: TTelevisor_State( pTv )
{
printf( "[constructed] CTVState_PowerOnOff()\n" );
}
void CTVState_PowerOnOff::putInput( char c )
{
if( c != '*' )
return;
getParent()->m_bIsTurnedOn = !getParent()->m_bIsTurnedOn;
if( getParent()->m_bIsTurnedOn )
getParent()->setState( new CTVState_Idle( getParent() ) );
else
getParent()->setState( NULL );
}
CTVState_Idle::CTVState_Idle( CTelevisor * const pTv )
: TTelevisor_State( pTv )
{
printf( "[constructed] CTVState_Idle()\n" );
printf( "\tTV is idling at channel %d\n", getParent()->m_iChannel );
}
void CTVState_Idle::putInput( char c )
{
if( !::isdigit( c ) )
return;
CTVState_PickChannel * pChannel = new CTVState_PickChannel( getParent() );
getParent()->setState( pChannel );
pChannel->putInput( c );
}
CTVState_PickChannel::CTVState_PickChannel( CTelevisor * const pTv )
: TTelevisor_State( pTv )
{
printf( "[constructed] CTVState_PickChannel()\n" );
}
void CTVState_PickChannel::putInput( char c )
{
if( !::isdigit( c ) )
return;
m_sNewChannel << c;
if( m_sNewChannel.str().length() != 2 )
return;
m_sNewChannel >> getParent()->m_iChannel;
getParent()->setState( new CTVState_Idle( getParent() ) );
}
Standardowe wyjście programu:
powerOn()
[constructed] CTVState_PowerOnOff()
[constructed] CTVState_Idle()
TV is idling at channel 1
[constructed] CTVState_PickChannel()
[constructed] CTVState_Idle()
TV is idling at channel 10
powerOff()
[constructed] CTVState_PowerOnOff()
powerOn()
[constructed] CTVState_PowerOnOff()
[constructed] CTVState_Idle()
TV is idling at channel 10
[constructed] CTVState_PickChannel()
[constructed] CTVState_Idle()
TV is idling at channel 7
powerOff()
[constructed] CTVState_PowerOnOff()
Wszystkie teksty są chronione prawami autorskimi. Kopiowanie lub rozpowszechnianie treści poza niniejszym serwisem
jest zabronione.
Powyższe ograniczenie nie dotyczy autora opracowania, któremu przysługuje prawo do rozpowszechniania własnego tekstu wedle własnego uznania.