#ifndef DECORATOR_H_INCLUDED
#define DECORATOR_H_INCLUDED
#include <string>
// --------------------------------------------------------------------------
/**
* @addtogroup interfaces Interfeisai
* @{
*/
class Decorator;
/**
* Abstraktus dokumentas. Galima jį peržiūrinėti, spausdinti, redaguoti.
*
* Taip pat pateikiamos funkcijos darbui su dekoratoriais.
*/
class Document {
public:
/** Konstruktorius. */
Document() {}
/** Virtualus destruktorius. */
virtual ~Document() = 0;
// Darbas su dokumentais
/** Galime dokumentą peržiūrėti. */
virtual void view() = 0;
/** Galime dokumentą spausdinti. */
virtual void print() = 0;
/** Galime dokumentą redaguoti. */
virtual void edit() = 0;
// Darbas su dekoratoriais
/**
* Grąžina nurodyto tipo dekoratorių.
*
* Jei dekoratorių grandinėje yra daugiau nei vienas nurodyto tipo
* dekoratorius, gražina išoriškiausią. Jei nurodyto tipo dekoratoriaus
* nėra, grąžina 0.
*
* Taisyklės primena dynamic_cast<>, t.y., jei objektas yra dekoruotas ne
* pačios DecoratorType klasės, bet iš jos išvestos poklasės dekoratoriumi,
* jis bus grąžinamas.
*
* Jei norite rasti visus nurodyto tipo dekoratorius, darykite šitaip:
*
* <pre>
* for (Document* tmp = document;
* DecoratorType* d = tmp->decorator<DecoratorType>();
* tmp = d->next())
* {
* // do something with d
* }
* </pre>
*/
template<typename DecoratorType> DecoratorType* decorator();
/**
* Grąžina dokumentą be nurodyto tipo dekoratoriaus.
*
* Parametras all sako, ar reikia išmesti visus nurodyto tipo dekoratorius
* (jei true), ar tik išoriškiausią (jei false).
*
* Išmesti dekoratoriai (jei tokių buvo) sunaikinami.
*
* Taisyklės primena dynamic_cast<>, t.y., jei objektas yra dekoruotas ne
* pačios DecoratorType klasės, bet iš jos išvestos poklasės dekoratoriumi,
* jis bus išmetamas.
*/
template<typename DecoratorType> Document* unwrap(bool all);
/**
* Grąžina kitą objektą dekoratorių grandinėje. Jei objektas nedekoruotas,
* grąžina 0.
*/
virtual Document* next() const { return 0; }
private:
/**
* Nustato kitą objektą dekoratorių grandinėje.
*
* Funkcija reikalinga norint realizuoti dekoratoriaus išmetimą iš
* sąrašo unwrap metode.
*/
virtual void setNext(Document* next) {}
};
/// @}
template<typename DecoratorType>
DecoratorType* Document::decorator()
{
if (DecoratorType* p = dynamic_cast<DecoratorType*>(this))
return p;
else if (Document * n = next())
return n->decorator<DecoratorType>();
else
return 0;
}
template<typename DecoratorType>
Document* Document::unwrap(bool all)
{
if (dynamic_cast<DecoratorType*>(this)) {
Document * n = next();
setNext(0);
delete this;
return n;
} else {
setNext(next()->unwrap<DecoratorType>(all));
return this;
}
}
/// @{
/**
* Abstraktus dekoratorius.
*/
class Decorator : public Document {
Document* next_; ///< Dekoruotas objektas
public:
/**
* Konstruktorius.
*
* Dekoruotas objektas @a next gali būti 0, bet tik tuo atveju, jei
* dekoratorių naudosite kaip parametrą unwrap arba decorator funkcijoms ir
* niekam daugiau.
*/
Decorator(Document* next)
: next_(next) {}
/** Destruktorius. Taip pat sunaikina ir dekoruotą objektą. */
~Decorator() = 0;
// Darbas su dokumentu
void view() { next_->view(); }
void print() { next_->print(); }
void edit() { next_->edit(); }
// Darbas su dekoratoriais
Document* next() const { return next_; }
private:
void setNext(Document* next) { next_ = next; }
};
/// @}
// --------------------------------------------------------------------------
/**
* @addtogroup documents Konkretūs dokumentai
* @{
*/
/**
* Tekstinis dokumentas.
*/
class TextDocument : public Document {
public:
// Darbas su dokumentais
void view();
void print();
void edit();
};
/**
* Paveiksliukas.
*/
class Image : public Document {
public:
// Darbas su dokumentais
void view();
void print();
void edit();
};
/// @}
// --------------------------------------------------------------------------
/**
* @addtogroup decorators Konkretūs dekoratoriai
* @{
*/
/**
* Nemodifikuojamas dokumentas.
*/
class ReadOnly : public Decorator
{
public:
explicit ReadOnly(Document* next)
: Decorator(next) {}
void edit();
};
/**
* Anotacija skaitytojui.
*/
class Annotation : public Decorator
{
std::string annotation_;
public:
Annotation(Document* next, const std::string& annotation)
: Decorator(next), annotation_(annotation) {}
void view();
void print();
// Papildomas funkcionalumas
/** Grąžina anotaciją. */
const std::string& annotation() const
{ return annotation_; }
/** Pakeičia anotaciją. */
void changeAnnotation(const std::string& annotation)
{ annotation_ = annotation; }
};
/// @}
// --------------------------------------------------------------------------
#endif
syntax highlighted by Code2HTML, v. 0.9.1