class Document:
    """
    Abstraktus dokumentas.  Subklasės turėtų realizuoti metodus view,
    printIt bei edit.
    """

    def decorator(self, subtype):
        """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 None.
        """
        return None

    def allDecorators(self, subtype):
        """Grąžina visus tipo dekoratorius sąraše."""
        return []

    def unwrap(self, subtype, all):
        """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).
        """
        return self

    def next(self):
        """Grąžina kitą objektą dekoratorių grandinėje.  Jei objektas
        nedekoruotas, grąžina None
        """
        return None

class Decorator(Document):
    """Abstraktus dekoratorius"""

    def __init__(self, next):
        """Konstruktorius."""
        self._next = next

    def __getattr__(self, attr):
        """Deleguojame priėjimą prie visų kitų atributų tikrajam objektui."""
        return getattr(self._next, attr)

    def decorator(self, subtype):
        if isinstance(self, subtype):
            return self
        else:
            return self._next.decorator(subtype)

    def allDecorators(self, subtype):
        if isinstance(self, subtype):
            result = [self]
        else:
            result = []
        return result + self._next.allDecorators(subtype)

    def unwrap(self, subtype, all):
        if isinstance(self, subtype):
            if all:
                return self._next.unwrap(subtype, all)
            else:
                return self._next
        else:
            return self._next.unwrap(subtype, all)

    def next(self):
        return self._next

class TextDocument(Document):
    """Tekstinis dokumentas"""

    def view(self):
        print "tekstinio dokumento peržiūra"
    def printIt(self):
        print "tekstinio dokumento spausdinimas"
    def edit(self):
        print "tekstinio dokumento redagavimas"

class Image(Document):
    """Paveiksliukas"""

    def view(self):
        print "paveiksliuko peržiūra"
    def printIt(self):
        print "paveiksliuko spausdinimas"
    def edit(self):
        print "paveiksliuko redagavimas"

class ReadOnly(Decorator):
    """Nemodifikuojamas dokumentas"""

    def edit(self):
        print "negalima redaguoti šio dokumento!"

class Annotation(Decorator):
    """Anotacija skaitytojui"""

    def __init__(self, next, annotation):
        """Konstruktorius"""
        Decorator.__init__(self, next)
        self._annotation = annotation

    def view(self):
        self.next().view()
        print "  anotacija:", self._annotation

    def printIt(self):
        self.next().printIt()
        print "  anotacija:", self._annotation

    def annotation(self):
        """Grąžina anotaciją"""
        return self._annotation

    def changeAnnotation(self, annotation):
        """Pakeičia anotaciją"""
        self._annotation = annotation

if __name__ == "__main__":

    # Sukuriame objektus
    txt = TextDocument()
    img = Image()

    # Bazinis funkcionalumas
    print "* Bazinis funkcionalumas";
    txt.view();
    txt.printIt();
    txt.edit();
    img.view();
    img.printIt();
    img.edit();
    print

    # Prikabiname dekoratorius
    txt = Annotation(txt, "įdomus dokumentas");
    txt = ReadOnly(txt);

    img = Annotation(img, "gražus paveiksliukas");
    img = Annotation(img, "o man nepatiko");

    # Bazinis funkcionalumas su dekoratoriais
    print "* Bazinis funkcionalumas su dekoratoriais";
    txt.view();
    txt.printIt();
    txt.edit();
    img.view();
    img.printIt();
    img.edit();
    print

    # Papildomas funkcionalumas
    print "* Papildomas funkcionalumas: pakeiskime anotaciją";
    if 0: # galima taip
        a = txt.decorator(Annotation)
        if a:
            a.changeAnnotation("o gal ir nelabai įdomus");
            txt.view()
    else: # o galima šitaip
        try:
            txt.changeAnnotation("o gal ir nelabai įdomus");
            txt.view()
        except AttributeError:
            pass
    print

    # Parodykime visas anotacijas
    print "* Pereikime per visus vieno tipo dekoratorius";
    for d in img.allDecorators(Annotation):
        print "radau anotaciją:", d.annotation()
    print

    # Nuimkime dekoratorių
    print "* Nuimkime ReadOnly dekoratorių";
    txt = txt.unwrap(ReadOnly, 1);
    txt.edit();
    print



syntax highlighted by Code2HTML, v. 0.9.1