Wzorce projektowe (21)
Autor: Damian Chodorek • Opublikowany: 24 lipca 2015 • Kategoria: kursy, wzorce projektowe
Stan.
Stan to wzorzec obiektowy. Umożliwia zmianę zachowania obiektu poprzez zmianę jego stanu wewnętrznego, ułatwia rozbudowę obiektu o nowe stany.
Klasy
class State{/*
klasa abstrakcyjna, po której dziedziczą wszystkie stany
*/};
// klasy konkretnych stanów
class ConcreteState1: public State{};
class ConcreteState2: public State{};
class ConcreteState3: public State{};
class StateContext{/*
klasa ustawiająca któryś z konkretnych stanów; jej metody wywołują metody stanu
*/};
class Client{/*
komunikuje się tylko z interfejsem StateContext
*/};
Etapy działania
- Klient tworzy obiekt
StateContext
. - Ustawia obiektowi konkretny stan.
- Wykonuje metody i zmienia stan jeśli zajdzie potrzeba.
Konsekwencje
- dane, które mają być trwałe muszą zostać zapisane do obiektu głównego, gdyż stan jest obiektem tymczasowym,
- dane tymczasowe powinny być trzymane w obiekcie stanu do czasu uzyskania kompletnych informacji, a wtedy powinny przekazać je do obiektu głównego,
- bardzo łatwo jest dodawać nowe stany.
Przykład
#include <string>
#include <iostream>
using namespace std;
///klasy pomocnicze
class Point
{
public:
int x,y;
};
class Rectangle
{
public:
void set(Point p1, Point p2)
{
begin=p1;
end=p2;
cout<<"Wybrano zaznaczenie od: "<<p1.x<<","<<p1.y<<
" do: "<<p2.x<<","<<p2.y<<endl;
}
private:
Point begin, end;
};
///klasa stanu
class AbstractTool {
public:
virtual void MoveTo(const Point& inP) = 0;
virtual void MouseDown(const Point& inP) = 0;
virtual void MouseUp(const Point& inP) = 0;
virtual ~AbstractTool(){}
};
///konkretne stany
class PenTool : public AbstractTool
{
public:
PenTool() : mMouseIsDown(false) {}
virtual void MoveTo(const Point& inP)
{
if(mMouseIsDown)
{
DrawLine(mLastP, inP);
}
mLastP = inP;
}
virtual void MouseDown(const Point& inP)
{
mMouseIsDown = true;
mLastP = inP;
}
virtual void MouseUp(const Point& inP)
{
mMouseIsDown = false;
}
private:
bool mMouseIsDown;
Point mLastP;
void DrawLine(Point p1, Point p2)
{
cout<<"Narysowana linia od: "<<p1.x<<","<<p1.y<<
" do: "<<p2.x<<","<<p2.y<<endl;
}
};
class SelectionTool : public AbstractTool
{
public:
SelectionTool() : mMouseIsDown(false) {}
virtual void MoveTo(const Point& inP)
{
if(mMouseIsDown)
{
mSelection.set(mLastP, inP);
}
}
virtual void MouseDown(const Point& inP)
{
mMouseIsDown = true;
mLastP = inP;
mSelection.set(mLastP, inP);
}
virtual void MouseUp(const Point& inP)
{
mMouseIsDown = false;
}
private:
bool mMouseIsDown;
Point mLastP;
Rectangle mSelection;
};
///Kontekst stanu
class DrawingController
{
public:
DrawingController() :currentTool(NULL) { selectPenTool(); } //na początek wybieramy stan domyślny
void MoveTo(const Point& inP) {currentTool->MoveTo(inP); }
void MouseDown(const Point& inP) {currentTool->MouseDown(inP); }
void MouseUp(const Point& inP) {currentTool->MouseUp(inP); }
void selectPenTool()
{
delete currentTool;
currentTool=new PenTool();
}
void selectSelectionTool()
{
delete currentTool;
currentTool=new SelectionTool();
}
private:
AbstractTool* currentTool;
};
int main(int argc, const char* argv[])
{
DrawingController dc;
Point point;
point.x=0;
point.y=0;
dc.MouseDown(point);
point.x=20;
point.y=20;
dc.MoveTo(point);
dc.MouseUp(point);
dc.selectSelectionTool();
point.x=0;
point.y=0;
dc.MouseDown(point);
point.x=20;
point.y=20;
dc.MoveTo(point);
dc.MouseUp(point);
}
Kolejna część już wkrótce.