Search code examples
pythonvisitor-pattern

Decorator pattern log each before and after


I want to log each iteration of my text changes nevertheless not sure what should be the proper way of doing that. See below. The first test is GeeksforGeeks and last one will be <i><u><b>GeeksforGeeks</b></u></i>. I want to print text changes on each iteration. I know i can do it like this to see each iteration by adding LoggingWrapper before every other wrapper like this:

gfg = LoggerWrapper(ItalicWrapper(LoggerWrapper(
        UnderlineWrapper(LoggerWrapper(BoldWrapper(LoggerWrapper(start)))))))

So then i see what i want to see:

LOG: GeeksforGeeks
LOG: <b>GeeksforGeeks</b>
LOG: <u><b>GeeksforGeeks</b></u>
LOG: <i><u><b>GeeksforGeeks</b></u></i>

But i am not sure either is it fine approach or should i do this differently? Ya, this way i can decide on which step i want to see the log right? Is it right way or?

My code:

class WrittenText:

    """Represents a Written text """

    def __init__(self, text):
        self._text = text

    def render(self):
        return self._text


class UnderlineWrapper(WrittenText):

    """Wraps a tag in <u>"""

    def __init__(self, wrapped):
        self._wrapped = wrapped

    def render(self):
        return "<u>{}</u>".format(self._wrapped.render())


class ItalicWrapper(WrittenText):

    """Wraps a tag in <i>"""

    def __init__(self, wrapped):
        self._wrapped = wrapped

    def render(self):
        return "<i>{}</i>".format(self._wrapped.render())


class BoldWrapper(WrittenText):

    """Wraps a tag in <b>"""

    def __init__(self, wrapped):
        self._wrapped = wrapped

    def render(self):
        return "<b>{}</b>".format(self._wrapped.render())


class LoggerWrapper(WrittenText):

    """Makes log"""

    def __init__(self, wrapped):
        self._wrapped = wrapped

    def render(self):
        result = self._wrapped.render()
        print("LOG: " + result)
        return result


""" main method """

if __name__ == '__main__':

    start = WrittenText("GeeksforGeeks")
    gfg = LoggerWrapper(ItalicWrapper(
        UnderlineWrapper(BoldWrapper(LoggerWrapper(start)))))

    gfg.render()

Solution

  • You can iterate through a sequence of wrappers to be applied to the text, and wrap each wrapper call with LoggerWrapper:

    gfg = 'GeeksforGeeks'
    
    for wrapper in WrittenText, BoldWrapper, UnderlineWrapper, ItalicWrapper:
        gfg = LoggerWrapper(wrapper(gfg))
    
    gfg.render()