Wzorce projektowe (16)
Autor: Damian Chodorek • Opublikowany: 24 lipca 2015 • Kategoria: kursy, wzorce projektowe
Łańcuch zobowiązań.
Jest to wzorzec obiektowy. Sprawia by dane zadania w zależności od swojego typu były przetwarzane przez różne obiekty.
Klasy
class Handler{/*
definiuje interfejs do przetwarzania zadań
*/};
/*
Klasy odpowiadające za to, aby przetworzyć żądanie w jakiś sposób, a jeżeli nie potrafią tego zrobić, wysyłają je do następcy.
*/
class RequestHandler1st: public Handler{};
class RequestHandler2nd: public Handler{};
class RequestHandler3rd: public Handler{};
class Client{/*
wysyła obiekt reprezentujący żądanie do pierwszego obiektu zajmującego się jego przetworzeniem (obiekty są w łańcuchu)
*/};
Etapy działania
- Klient tworzy obiekty zajmujące się zadaniami i ustawia je w łańcuch (ustala następników).
- Wysyła żądanie oraz informację o jego typie.
- Obiekt zajmujący się reakcją na żądanie jeśli potrafi to je obsługuje, jeśli nie to wysyła do następnego (któryś z nich musi je przetworzyć).
Konsekwencje
Zalety:
- elementy łańcucha mogą być dynamicznie dodawane lub usuwane w trakcie działania programu,
- zmniejsza zależność pomiędzy nadawcą i odbiorcą,
- implementacja pojedynczej procedury nie musi znać struktury łańcucha oraz innych procedur.
Wady:
- wzorzec NIE gwarantuje, ze każde zadanie zostanie obsłużone (tylko te, których typy zna),
- śledzenie i debugowanie pracy działania łańcucha może być trudne.
Przykład
#include <iostream>
#include <string>
using namespace std;
///abstrakcyjna klasa, po której dziedziczą klasy zajmujące się zadaniami
class Logger
{
public:
const static int ERR=3;
const static int NOTICE=5;
const static int DEBUG=7;
Logger() : _next(0){}
Logger * setNext(Logger *l)
{
_next=l;
return this;
}
virtual void message (string m, int priority)=0;
protected:
Logger* _next;
int _mask;
void WriteToLog(string str)
{
cout<<str<<endl;
}
};
class DebugLogger : public Logger
{
public:
DebugLogger(int mask){_mask=mask;}
void message (string m, int priority)
{
if(priority <= _mask) WriteToLog("Debug: "+m);
if(_next!=0)_next->message(m,priority);
}
};
class MailLogger : public Logger
{
public:
MailLogger(int mask){_mask=mask;}
void message (string m, int priority)
{
if(priority <= _mask) WriteToLog("Mail: "+m);
if(_next!=0)_next->message(m,priority);
}
};
class StdErrLogger : public Logger
{
public:
StdErrLogger(int mask){_mask=mask;}
void message (string m, int priority)
{
if(priority <= _mask) WriteToLog("StdErrLogger: "+m);
if(_next!=0)_next->message(m,priority);
}
};
int main(int argc, const char* argv[])
{
// Logger *l=(new DebugLogger(Logger::DEBUG))->setNext(
//(new MailLogger(Logger::NOTICE))->setNext((new StdErrLogger(Logger::ERR)) ) );
StdErrLogger stdd(Logger::ERR);
MailLogger mail(Logger::NOTICE);
mail.setNext(&stdd);
DebugLogger dbg(Logger::DEBUG);
dbg.setNext(&mail);
Logger *l=&dbg;
l->message("wiadomosc loggera", Logger::ERR);
}