Wyjaśnienie lekcji
Po tej lekcji będziesz potrafić:
Dziedziczenie mówi, że jedna klasa jest rodzajem innej klasy (class PremiumAccount(Account)). Kompozycja mówi, że obiekt ma inny obiekt, który pomaga mu w pracy (Notifier ma Formatter). Oba wzorce są użyteczne, ale dziedziczenie powinno odzwierciedlać prawdziwą relację typów, a nie być skrótem do ponownego użycia kodu.
W kompozycji konstruktor obiektu zewnętrznego otrzymuje obiekt współpracujący i go przechowuje. Następnie deleguje pracę: self.formatter.render(message). Dostarczenie obiektu współpracującego z zewnątrz (wstrzykiwanie przez konstruktor) ułatwia zmianę zachowania i testowanie klasy zewnętrznej bez jej edycji.
Nie twórz automatycznie w konstruktorze zastępczego obiektu współpracującego, gdy wywołujący dostarczył własny; zignorowałoby to wybrane zachowanie. Kompozycja pozwala też uniknąć długich łańcuchów dziedziczenia, gdy jedynym celem jest połączenie oddzielnych odpowiedzialności.
class Formatter:
def render(self, value):
return value.upper()
class Service:
def __init__(self, formatter):
self.formatter = formatter
def output(self, value):
return self.formatter.render(value)
service = Service(Formatter())
print(service.output("ready"))Wynik:
READYDwa formattery mają tę samą metodę, ale dają różne wyniki.
class PlainFormatter:
def render(self, message):
return message
class BracketFormatter:
def render(self, message):
return f"[{message}]"
class Reporter:
def __init__(self, formatter):
self.formatter = formatter
def report(self, message):
return self.formatter.render(message)
print(Reporter(PlainFormatter()).report("ok"))
print(Reporter(BracketFormatter()).report("ok"))Wynik:
ok
[ok]Dziedziczenie jest właściwe, gdy klasa potomna naprawdę jest wyspecjalizowanym typem swojej klasy nadrzędnej.
class Storage:
def kind(self):
return "storage"
class CloudStorage(Storage):
def kind(self):
return "cloud storage"
print(CloudStorage().kind())Wynik:
cloud storageMagazyn w chmurze jest rodzajem magazynu; usługa ma formatter.
class RetryPolicy:
def can_retry(self, attempt):
return attempt < 3
class Worker:
def __init__(self, policy):
self.policy = policy
def should_retry(self, attempt):
return self.policy.can_retry(attempt)
print(Worker(RetryPolicy()).should_retry(2))Wynik:
True| Relacja | Przykład | Znaczenie |
|---|---|---|
| Dziedziczenie (jest) | class Admin(User) | Wyspecjalizowany typ |
| Kompozycja (ma) | Report(formatter) | Używa innego obiektu |
| Wstrzykiwanie zależności | self.formatter = formatter | Zachowanie przekazanego obiektu współpracującego |
| Delegowanie | self.formatter.render(text) | Poproszenie obiektu współpracującego o wykonanie jego zadania |
self.formatter).