Het ontwerppatroon van de decorateur lijkt een beetje op een wafel

Het decorateurpatroon gaat over het toevoegen van extra functies aan een bestaand object.

Klinkt dat als Frans?

Maak je geen zorgen.

We komen hier later op terug.

Laten we eerst enkele wafels bekijken!

Het geniale deel van wafels is dat ze eenvoudig beginnen. Omdat ze eenvoudig zijn, smaakt bijna alles goed bij hen

Enkele veel voorkomende toppings voor wafels zijn aardbeien, bosbessen, bramen, bananen, amandelen en siropen.

Laten we proberen een verzameling verschillende wafelobjecten te maken.

Er zijn StrawberryWaffle, BlueberryWaffle, BlackberryWaffle, BananaWaffle, AlmondWaffle en SyrupWaffle.

Wacht, we kunnen aardbeien en bosbessen op dezelfde wafel hebben. Dit geeft ons een StrawberryBlueberryWaffle.

We kunnen ook aardbeien en bramen op dezelfde wafel hebben. Dit geeft ons een Strawberry Blackberry Wafel.

Niemand verbiedt ons om drie toppings op dezelfde wafel te leggen. Dit geeft ons een StrawberryBlueberryBlackberryWaffle.

Laten we om het eenvoudig te houden aardbeien, bosbessen en bramen als potentiële toppings beschouwen. Er zijn acht verschillende combinaties [1].

Betekent dit dat we acht verschillende objecten moeten maken voor onze wafelcollectie?

Als we bananen toevoegen aan onze lijst met mogelijke toppings, zijn er 16 verschillende combinaties [2].

Het is duidelijk dat het toevoegen van een enkele topping aan onze toppingslijst een explosie in onze wafelcollectie veroorzaakt.

Het is niet haalbaar om voor elke mogelijke combinatie van toppings een andere wafelklasse te maken. Er moet een betere manier zijn om dit te doen.

Wat als we, wanneer we een StrawberryWaffle willen in plaats van een StrawberryWaffle, we een Waffle maken en er aardbeien aan toevoegen?

Hoe zit het dan met StrawberryBlueberryWaffle?

We kunnen een wafel maken, er aardbeien aan toevoegen en bosbessen aan toevoegen!

Wafelklassen maken

Laten we de gewone wafelklasse eens bekijken:

Je kunt een wafel maken, serveren en als volgt eten:

En hier is de StrawberryWaffle-klasse:

Merk op dat we een wafelobject binnen de StrawberryWaffle-constructor passeren om een ​​StrawberryWaffle te maken.

De StrawberryWaffle-klasse heeft:

  1. De doorgegeven wafel
  2. Aardbeien als topping
  3. Een serve-methode die de doorgegeven wafel serve-methode aanroept. Vervolgens worden prints gegarneerd met aardbeien
  4. Een eetmethode die de doorgegeven eetmethode van de wafel aanroept en vervolgens wat aardbeien print en vervolgens opeet

Je kunt een aardbeienwafel maken, serveren en als volgt eten:

Hier zijn de klassen BlueberryWaffle en BlackberryWaffle:

En u kunt ze als volgt gebruiken:

Het gemeenschappelijke gedeelte eruit trekken

We merken dat de StrawberryWaffle-klasse, de BlueberryWaffle-klasse en de BlackberryWaffle-klasse bijna identiek zijn, behalve hun topping, we kunnen de gemeenschappelijke delen eruit halen als een ouderklasse.

In WaffleDecorator is topping niet langer een kenmerk van het object. In plaats daarvan is het een methode die door een kindklasse kan worden opgeheven.

Nu kunnen we StrawberryWaffle, BlueberryWaffle en BlackberryWaffle herschrijven om WaffleDecorator te erven om deze gemeenschappelijke functies te verkrijgen:

En ze moeten nog steeds hetzelfde werken als voorheen:

Dit zijn de klassen die we maken:

Een BlueberryStrawberry-wafel maken

Nu hebben we Waffle, StrawberryWaffle, BlueberryWaffle en BlackberryWaffle.

Het is tijd om het doel te bereiken dat we oorspronkelijk hadden vastgesteld:

maak een wafel, voeg er aardbeien aan toe en voeg bosbessen toe.

Net als dit:

En we kunnen:

Wat gebeurt er?!

Laten we eens nader kijken hoe we de blueberry_strawberry_waffle hebben gemaakt:

Eerst hebben we een plain_waffle gemaakt met Waffle: plain_waffle = Waffle.new

Vervolgens creëerden we strawberry_waffle door de plain_waffle in de StrawberryWaffle-constructor te brengen. strawberry_waffle = StrawberryWaffle.new (plain_waffle)

Het is vermeldenswaard dat wanneer we de aardbei_wafel maken, we de doorgegeven gewone_wafel houden als een instantievariabele van aardbei_wafel:

Zoals we kunnen zien, zijn strawberry_waffle.waffle en plain_waffle hetzelfde object:

Op dit punt, wanneer we strawberry_waffle.serve aanroepen. We noemen eerst plain_waffle.serve en drukken vervolgens af met aardbeien.

Voor strawberry_waffle.eat noemen we eerst gewoon_waffle.eat, drukken vervolgens af en eten wat aardbeien.

We maken blueberry_strawberry_waffle door de strawberry_waffle door te geven aan de BlueberryWaffle-constructor. blueberry_strawberry_waffle = BlueberryStrawberryWaffle.new (strawberry_waffle)

Wanneer we de blueberry_strawberry_waffle maken, houden we de doorgegeven aardbei_waffle als een instantievariabele van blueberry_strawberry_waffle:

Als we blueberry_strawberry_waffle.serve aanroepen, noemen we eerst aardbei_waffle.serve. Dat noemt plain_waffle.serve en drukt vervolgens af met aardbeien. Druk vervolgens af met bosbessen.

Wanneer we blueberry_strawberry_waffle.eat noemen, noemen we eerst aardbei_waffle.eat. Dat noemt plain_waffle.eat en drukt vervolgens af en eet dan wat aardbeien. Druk vervolgens af en eet wat bosbessen.

De sleutel van de magie:

strawberry_waffle is gebouwd bovenop plain_waffle. En blueberry_strawberry_waffle is gebouwd bovenop aardbei_wafel.

De sleutel om wafels bovenop elkaar te kunnen bouwen, is dat alle wafels dezelfde interface moeten hebben.

Alle wafels hebben een serve-methode en een eet-methode.

Dat is de reden waarom we binnen de StrawberryWaffle / BlueberryWaffle / BlackberryWaffleclasses ervan overtuigd zijn dat de doorgegeven wafel een serveermethode en een eetmethode heeft.

En we kunnen de serveermethode en de eetmethode van de doorgegeven wafel gebruiken bij het definiëren van een nieuwe serveermethode en een nieuwe eetmethode.

Een WaffleDecorator geeft niet om het soort wafel. Het kan een gewone wafel, een aardbeiwafel of een buitenaardse wafel zijn.

Het enige dat telt is dat een WaffleDecorator een wafel neemt en een verbeterde wafel retourneert. De wafel die nodig is en de wafel die hij terugkeert, hebben dezelfde interface.

Omdat alle decorateurs die wafels nemen en retourneren dezelfde interface volgen, kan het resultaat van een decorateur worden doorgegeven aan een andere decorateur.

Net als dit:

of dit:

Nu met Waffle, StrawberryWaffle, BlueberryWaffle en BlackberryWaffle kunnen we alle acht verschillende wafels maken.

Banaan toevoegen aan onze toplijst is net zo eenvoudig als:

Je hebt zojuist het decorateurpatroon geleerd!

Hier is de definitie:

Decorateur voegt dynamisch extra verantwoordelijkheden toe aan een object.

Takeaways:

  1. Het decorateurpatroon gaat over het eenvoudig toevoegen van extra functies aan een bestaand object.
  2. Het object dat moet worden gedecoreerd (het object dat aan alle decorateurs wordt doorgegeven) en objecten die door decorateurs worden geretourneerd, moeten dezelfde interface volgen.

Bedankt voor het lezen! Ik hoop dat je geniet van het artikel.

Ik publiceer wekelijks op sihui.io.

Abonneer je zodat je het volgende artikel uit de serie niet mist.

De volgende keer zullen we kijken naar ...

[1] PlainWaffle, StrawberryWaffle, BlueberryWaffle, BlackberryWaffle, StrawberryBlueberryWaffle, StrawberryBlackberryWaffle, BlueberryBlackberryWaffle en StrawberryBlueberryBlackberryWaffle.

[2] C (4, 0) + C (4, 1) + C (4, 2) + C (4, 3) + C (4, 4) = 16