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

  1. Klient tworzy obiekty zajmujące się zadaniami i ustawia je w łańcuch (ustala następników).
  2. Wysyła żądanie oraz informację o jego typie.
  3. 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);
}

część 17

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.