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