lundi 4 décembre 2017

Is there a name/pattern for classes which call abstract handler methods

Imagine two classes TypeAServer and TypeBServer which implement some sort of functionality and need to call methods in case of some events. Apart from providing discrete callback functions I can think of two slightly different approaches when I want to implement composite behavior:

class TypeAServer(ABC):
    def __init__(self):
        do some stuff

    @abstractmethod
    def on_type_a_event(self, event):
        ''' will be called when event type A occurs '''

    def some_message_generating_method(self):
        ...
        self._handler.on_type_a_event(e)

class TypeBServer(ABC):
    def __init__(self):
        do some stuff

    @abstractmethod
    def on_type_b_event(self, event):
        ''' will be called when event type A occurs '''

    def some_message_generating_method(self):
        ...
        self._handler.on_type_b_event(e)

class CompositeServer(TypeAServer, TypeBServer):
    def __init__(self):
        TypeAServer.__init__(self)
        TypeBServer.__init__(self)

    def on_type_a_event(self, event):
        # implement reaction of event type A

    def on_type_b_event(self, event):
        # implement reaction of event type B

In this case I just inherit classes with abstract methods in order to implement the wanted behavior.

However - when I don't want to inherit TypeAServer and TypeBServer directly I can also go for a composition based approach like this:

class TypeAServer:
    class Handler(ABC):
        @abstractmethod
        def on_type_a_event(self, event):
            ''' will be called when event type A occurs '''

    def __init__(self, handler):
        self._handler = handler
        # do some other stuff

    def some_message_generating_method(self):
        ...
        self._handler.on_type_a_event(e)

class TypeBServer:
    class Handler(ABC):
        @abstractmethod
        def on_type_a_event(self, event):
            ''' will be called when event type A occurs '''

    def __init__(self, handler):
        self._handler = handler

    def some_message_generating_method(self):
        ...
        self._handler.on_type_b_event(e)

class CompositeServer(TypeAServer.Handler, TypeBServer.Handler):
    def __init__(self):
        self.type_a_server = TypeAServer(handler=self)
        self.type_b_server = TypeAServer(handler=self)

    def on_type_a_event(self, event):
        # implement reaction of event type A

    def on_type_b_event(self, event):
        # implement reaction of event type B

This second example is quite similar to the first one but it has some well known benefits (see composition over inheritance):

  • I can decide when I set up the server instances
  • I can even add more dynamically
  • Testing is simpler
  • Name collisions of internally called methods are less likely

My Question is now: I know terms like composition and interface - but is there a pattern for "injecting" an object which implements a "handler interface" on construction (in contrast to implicitly providing the handler through inheritance)?

Aucun commentaire:

Enregistrer un commentaire