Dieses Interface wurde für den Cheeseburger implementiert, das
heißt Brötchen, keine Ahnung, Patty, was kommt, da kommt da
überhaupt noch ne Gurke drauf, keine Ahnung was war da glaub
ich noch nie drauf. Ne.
Coding Buddies Dein Podcast rund um Softwareentwicklung und
aktueller Tech News herzlich Willkommen.
Einen wunderschönen guten Tag und herzlich Willkommen zur
neuen Folge vom Coding Buddies Podcast und Tino begrüße ich
hier ganz herzlich und ich hoffe, Tino, Du hast auch einen
so wunderschönen Tag, wie ich ihn gerade allen hier gewünscht.
Habe ja Moin Moin fabi, ja ich habe einen super Tag, es ist
tolles Wetter, ich genieße das so richtig drin zu sein und.
Um mit dir jetzt n Podcast aufzunehmen.
Ich hab Bock, ich hab Bock. Das ist sehr gut, das freut
mich. Wir haben nämlich auch heute
wieder n sehr interessantes Thema.
Also ich freu mich auf die Folge, ich hab da echt Bock
drauf, hab ich ja sonst auch immer, aber irgendwie weißt du
es gibt immer mal so da da da stehst du morgens auf und denkst
dir heute n Podcast aufnehmen. Fühl ich so mit dem Thema.
Ja, ich find es auch. Was haben wir denn so?
Wir haben ja n ganz cooles Thema heute und zwar wollen wir so
richtig durchstarten mit unserer neuen Reihe zum Thema Design
Pattern und quasi heute mal so das erste Pattern besprechen.
Doch bevor wir sagen, welches das ist und so richtig
reinstarten noch ganz kurz die Anmerkung, Liebe Zuhörer, liebe
Zuhörer, falls dir dieser Podcast gefällt, du den
Abfeierst, ihn vielleicht schon länger hörst, so Mehrwert
rausziehen kannst, schau doch mal in die Shownotes, da gibt es
einen kleinen Spendenlink. Falls du Bock hast zu uns zu
unterstützen, wir würden uns mega darüber freuen.
Das nur kurz als Anmerkung. Werbung ändern an dem Punkt.
Und deswegen fabi, Hau doch mal raus, was für ein Pattern kommt
heute, wir haben es ja in der Einleitungsfolge schon mal etwas
angeteasert und genau das haben wir auch jetzt gemacht.
Wir haben gesagt, wir nehmen einfach ein Pattern, was ich
glaube einfach wirklich, wirklich, wirklich oft einem
über den Weg läuft und zwar das Factory Pattern und ich finde
auch persönlich ist es auch ein. Pattern, was ich auch häufig
sehe, häufig nutze also auch selber und ich finde irgendwie,
das ist so ein Klassiker und deswegen können wir einfach mal
mit diesem Klassiker einfach anfangen und durchstarten und
einfach mal gucken okay ne, was ist das, wann nutzt man das,
wofür benutzt man das? Und diese Fragen klären wir
einfach mal alle und zeigen natürlich, was es also wie das
aufgebaut ist, ne. Genau, also wir hatten ja
gesagt, dass wir uns heute das Factory Pattern anschauen
wollen. Und in der Einleitungsfolge sag
ich mal, haben wir ja auch gesagt, warum Pattern so wichtig
sind. Noch mal kurz genannt, um
einfach Strukturen den Code zu kriegen, besser testbaren Code
zu haben, Skalierbarer und Wartbarer zu sein und das kann
man am Factory Pattern auch ganz gut schon sehen und deswegen ist
es auch n super einstiegspattern sag ich mal, weil man kann es
auch mit. Mit Analogien gut erklären und
ich weiß, du bist Fan von Analogien.
Fabi, da kannst du dich richtig austoben heute aber mal ganz
kurz allgemein, warum überhaupt Factory pattern?
Also wir bewegen uns heute so n bisschen in der
objektorientierten Welt, das noch als Anmerkung dazu.
Ja. Und jeder, der vielleicht gerade
am Anfang ist, sich mit der Objektorientierung zu
beschäftigen, beispielsweise mit Javas startet und da ja
notgedrungen in die Objektorientierung kommt, was ja
nichts Schlechtes ist. Nicht falsch verstehen, aber der
wird das Halt merken, dass gerade am Anfang, dann hast du
überall New im Code, überall werden Objekte erzeugt, du weißt
gar nicht mehr, auf welchen du jetzt arbeiten sollst.
Du hast ne hohe Kopplung des Codes, du kannst das nicht mehr
so wirklich extrahierend voneinander und.
Wie sagt man so schön Dead escalated Quickly?
Also du kommst halt dann auch schnell an den Punkt, wo es
einfach unübersichtlich wird und da möchte ich wirklich mal mit
einer Analogie starten. Fabi, Ich hoffe du greifst die
auf oder hast vielleicht noch ne andere damit man sich das Ganze
einfach mal vorstellen kann wie man jetzt mit Hilfe eines
Factory Patterns. Mehr Struktur in seinen Code
bekommt. Und zwar möchte ich da, dass ihr
euch alle, liebe Zuhörer, liebe Zuhörer, du und vor allem auch
du Fabi euch folgendes vorstellt.
Ihr seid beispielsweise wieder in der Schule oder an der Uni,
ihr hattet eine anstrengende Vorlesung deswegen oder oder
gerade Unterricht und ihr seid so richtig ausgelaugt und was
wäre jetzt besser als ein kühles Getränk, weil es ist warm
draußen ja, also du hast jetzt so richtig Bock auf ein kaltes
Getränk und. Und dann steht er da, am Ende
des Ganges, leuchtend der Getränkeautomat, und du rennst
dahin mit deinen letzten Münzen in der Tasche und möchtest dir
jetzt noch ein schönes kaltes Getränk holen und stehst davor
und siehst die verschiedenen Knöpfe, weißt erst mal gar
nicht, was du nehmen sollst. Nimmst du eine Cola, eine Cola
light, ein Wasser, eine Apfelschorle vielleicht und eine
Spezi gibt es auch für dich kein Problem, hat der Automat am
Start und. Und ja, was passiert jetzt?
Du schmeißt dein Geld rein und drückst einfach auf n Knopf und
sagst zum Beispiel Wasser und du bekommst ne Wasserflasche
daraus, vorzugsweise wahrscheinlich n halber Liter
PET Flasche, aber du bekommst n Wasser.
Hättest du jetzt Cola gedrückt, würde der Automat dir Cola
geben. Das heißt abhängig davon, was du
dem Automat als Eingabe gibst, kriegst du dementsprechend den
Output. Ja, und das kann man sich jetzt
wieso n neues Objekt getränkt vorstellen, nur das ist in dem
Fall wenn ich Wasser drücke und Wasser ist wenn ich Cola drücke
ist es ne Cola. Das heißt, in diesem Fall ist
der Automat genau diese Factory und das Pattern, was wir heute
besprechen wollen. Denn die Logik was du bekommst
an Getränk, also als Getränk, ist quasi intern im Automat
gegeben und abhängig von deiner Knopfeingabe sagen wir mal da
drin ist ne Art Switch. Ja FLS wie auch immer.
Wird entschieden, welches Getränk ausgegeben wird.
Das heißt, für dich spielt es gar keine Rolle, wie intern
ausgewählt wird. Es spielt für dich nicht mal
eine Rolle, wie dieses Getränk da überhaupt rein gekommen ist.
Dass das irgendwer aufgefüllt hat oder wie das Getränk
abgefüllt wurde oder was auch immer es spielt für dich in dem
Fall keine Rolle, sondern es spielt nur eine Rolle.
Ich möchte jetzt auf Wasser drücken und dann möchte ich
bitte auch ein Wasser bekommen, der Rest ist mir egal und.
Und ich finde, daran kann man das schon mal ganz gut erklären
oder beziehungsweise verstehen, was dieses Pattern eigentlich
für n Ziel hat am Ende. Ja, also du kriegst ja im
Endeffekt sozusagen ein, wenn man jetzt so n bisschen, weil du
ja auf Switch und IF und so eingegangen bist.
Du kriegst ja am Ende so so ne Art, ich sag mal Objekt Getränk.
Und was es dann aber speziell für ein Getränk ist, das ist im
Endeffekt erstmal, sage ich jetzt mal egal, weil das dieser
Getränkeautomat kann nur Getränke ausspucken und dann ist
es natürlich wichtig. Was ist es denn wirklich
speziell für ein Getränk? Also wenn du jetzt zum Beispiel
sagst Wasser ist dann zum Beispiel auf 1 und dann hast du
zum Beispiel if Eingabe 1 dann Wasser if Eingabe oder Else IF
oder so und so weiter und sofort oder mit dem Switch wie du
meintest um sich das jetzt mal ganz explizit vorzustellen und
dann kriegst du halt einfach dein dein Getränk da raus.
Ja finde ich gut, ich finde das. Also ich hab hätt noch ne andere
Analogie, vielleicht noch mal so n bisschen um die Vielfalt
rauszubringen. Wenn wir jetzt schon bei Cola
und und ungesunden Getränken waren, dann möchte ich jetzt
noch n ungesundes Essen ansprechen.
Oh, jetzt bin ich gespannt. Zum Beispiel Pizza, ne.
Also wenn ihr jetzt zum Beispiel was.
Ungesund. Ja, natürlich nicht.
Pizza ist sehr gesund, sollte man jeden Tag essen, mindestens
3, mindestens 3, ja wenn nicht mehr, nein, auf jeden Fall, ich
finde, daran kann man sich das auch oder kann ich mir das ganz
gut vorstellen, wenn man sagt okay, du gehst in eine Pizzeria
und möchtest jetzt eine Pizza bestellen und du weißt
eigentlich okay egal welche Pizza du bestellst, du hast
eigentlich immer den gleichen Pizzaboden, also der Teig von
dem Boden ist immer der gleiche. Die Soße da drauf, die
Tomatensoße auch immer die gleiche, ne so und dann ist
natürlich nur die Frage OK, was möchtest du jetzt drauf haben?
Ne du gehst jetzt zum Beispiel hin du sagst ich möchte ne
Salamipizza bestellen, also bekommst du halt eben diese
Grundpizza ne Teig und Tomatensoße plus dann Salami und
Käse drauf ne oder du sagst ich möchte ne Hawaii Pizza haben und
bekommst dann halt eben wieder diese Grundpizza mit halt
Schinken und Ananas ich glaub so.
Ungefähr geht nach Hawaii, bin ich jetzt nicht so Fan.
Von Hawaii hast du doch nur gewählt, um jetzt hier Leute zu
provozieren, die sagen Hawaii ist keine Pizza.
Ja, mal gucken, finde ich gut, finde ich gut, gleich war so
eine Grundsatzdiskussion jetzt hier ausbrechen lassen.
Ja ich bin auch kein Fan von Hawaii muss ich sagen, aber ist
ja Geschmackssache, Geschmackssache.
Genau, aber im Endeffekt gehst du ja eigentlich dann am Ende
aber auch nur hin und ne, also wenn du das ganze noch weiter
abstrahierst, hast du ja in vielen Restaurants auch einfach
nur zahlen, die dann zu mich dran stehen und sagst ja ich
möchte jetzt die 10 ne und 10 ist dann am Ende beispielsweise
die Salami ne und dann sagst du ich möchte aber zu mich die 14
und das ist dann aber die die Hawaii und wichtig ist ja nur,
dass du weißt, du möchtest eine Pizza Punkt 1 und Punkt 2 ist
welche denn genau ne? Dann sagst du halt entweder den
Namen oder die Zahl und bekommst dann halt eben am Ende diese
Pizza. Und wie das jetzt aber
hergestellt wird, wie du meintest ne keine Ahnung, du
brauchst nicht wissen wie der Belag aussieht beziehungsweise
wie der wie der da drauf gelegt wird, wie die Pizzateig Rezeptur
ist, was in die Tomatensoße kommt alles egal.
Das macht alles die Küche ne und wenn man das jetzt auf Code
Ebene sieht, dann ist die Küche der Defactory und.
Innerhalb der Factory weiß der Code, was da passieren soll,
aber du von außen, wenn du die benutzt diese Factory die
brauchst, da brauchst du es nicht wissen, du willst halt nur
die entsprechenden Pits und so ne.
Und. Das ist im Endeffekt dann ja
auch eine andere Analogie für so n Factory patter ne.
Ja, was man daran auch wirklich. Also es ist auch n sehr gute
Analogie, vielen Dank dafür, fabi.
Weil wir ein wichtiger Punkt der ne Factory auch noch mit sich
bringt. Also das Pattern kann man daran
nämlich auch ganz gut erklären. Angenommen jemand bestellt jetzt
ne Salamipizza, fängst du ja nicht an zu sagen ich setze
jetzt n Teig an, ich rühre jetzt die Soße an oder stell diese
Soße quasi her, hab dann den Teig, die Soße und dann den
spezifischen Belag für die Pizza drauf, ne um ne Salamipizza zum
Beispiel herzustellen, sagen wir mal das machst du ja nicht in
dem Fall, sondern du hast ja wie du meintest diese Grundsoße, die
ist fertig für alle Pizzen, das heißt du kannst sie wieder
verwenden und musst nicht jedes Mal neu definieren, wie diese
Soße aussieht, welche Kräuter da reinkommen, wie auch immer,
genauso der Teig, der ist fertig, das heißt du musst nicht
jedes Mal wieder neuen Teig herstellen, nur um jetzt ne
Salami oder was hast du gesagt ne Hawai Pizza zu machen.
Ja und daran kann man nämlich auch gut erkennen welche
Vorteile das mit sich bringt, weil du kannst ja sagen ich habe
diese Grundpizza und die hat Eigenschaften.
Ja, zum Beispiel der Teig sieht so und so aus, die Soße da drauf
ist in der und der Menge da drauf und so weiter und darauf
aufbauend spezifizierst du dann ja nur noch wie du meintest die
Pizza und kannst so quasi Objekte schnell und einfach
herstellen, in dem Fall die Pizza.
Wenn wir jetzt noch mal n bisschen in die Coderichtung
gehen, also quasi in deiner objektorientierung Objekte
herstellen ohne zu wissen wie genau sie im Detail gebaut sind,
wie der Teig aussieht, wie die Soße aussieht, aber du weißt du
kriegst ne Pizza. Plus die Parameter, die du
reingibst Salami oder Hawaii oder ne Nummer wie du meintest
und hast dann am Ende n fertiges Pizzaobjekt, was deinen
Ansprüchen entspricht, sag ich mal.
Der Code liefert es dir einfach ne und das ist eigentlich
wirklich ne perfekte Analogie um einfach mal.
Den Factory Pattern zu zeigen, also quasi auch diese Analogie
mal zu programmieren, einfach sich zu sagen, ich habe jetzt
ein eine basisklasse Pizza und habe dann spezifische Pizzen
sozusagen die ich erzeugen kann, also alle, die jetzt diese Folge
hören und das mal ausprobieren wollen, programmiert ruhig
danach mal. Diese Pizzeria ist eine sehr
geile Übung. Was ich ein bisschen, also was,
was mich früher am beim Start in die Softwareentwicklung, was
mich immer so. Ein bisschen verwundert hat an
diesem, an dieser Beschreibung von einer Factory, das das
heißt, die Factory gibt ja ein Objekt und wie dieses Objekt am
Ende gebaut wird, das ist dir egal, das brauchst du nicht
wissen, das wird von der Factory bereitgestellt, das Macht der
Code dahinter und du brauchst das Wissen darüber nicht und das
fand ich da dachte ich mal so, ich verstehe es nicht ganz am
Anfang, da dachte ich mir, so wie ich bau.
Bau doch diese Factory, dann weiß ich doch wie das
funktioniert. So weißt du da dachte ich mir
immer so, das macht doch gar keinen Sinn.
Natürlich weiß ich wie das da drin aussieht, natürlich muss
ich wissen wie das passiert und das war für mich damals immer so
ein kleiner wie sagt man so, da habe ich mir so ein bisschen den
Kopf drüber zerbrochen, im Endeffekt ist es ja so, dass
wenn du normalerweise später irgendwann mal in der
Softwareentwicklung arbeitest, dann.
Dann schreibst du ja nicht den kompletten Code für die gesamte
Anwendung. Das heißt, du schreibst
vielleicht an einer Stelle und jemand anders schreibt an einer
anderen Stelle, das heißt, eine Person hat beispielsweise diese
diese Factory erstellt und du kannst sie dann für deine
Aufgabe nutzen. Und in dem Fall ist es dann so,
dass du natürlich darauf vertrauen solltest, dass die
Factory funktioniert. Ist ja auch deine
Arbeitskollegin oder dein Arbeitskollege, der das dann
implementiert hat, aber du kannst dann einfach nur sagen,
OK, ich möchte jetzt Objekt AB oder C haben und das kriege ich
aus der Factory raus, ne und das ist halt so n bisschen das war
ich weiß nicht ob noch irgendjemand vielleicht genauso
mal an diesem Punkt war, aber das das hat mich früher.
Gerade im Studium habe ich das immer.
Ich dachte, was wollen die denn von mir.
Natürlich weiß ich, wie das alles aussieht, ich habe es ja
programmiert. Dann, ja, natürlich ist damit ja
nicht gemeint, dass du eine Blackbox hast.
Also gerade wenn du sie selbst entwickelst, also das Pattern
selbst implementierst, geht es ja nicht darum, eine Blackbox zu
haben, wo du nicht in den Code reingucken kannst.
Aber um die Wiederverwendbarkeit und Skalierbarkeit, das ist ja
das Entscheidende, dass du genau diese Factory an einer Stelle
definierst. Und dann das Hochskalieren
kannst, indem du dir halt verschiedene Implementierung
einer Pizza überlegst oder implementierst und die dann halt
wieder verwenden kannst. Über deine Factory und das
Entschlankt oder macht ja den Code schlank am Ende
unvorinkalierbar. Ja, genau.
Aber es gibt halt auch, um mal ein bisschen fachlicher zu
werden und so mal richtig in das Design Pattern reinzukommen.
Es gibt ja verschiedene Formen des Factory Patterns, es gibt
sozusagen so eine vereinfachte Factory, es gibt die klassische,
was auch als Design Pattern so quasi in jedem Buch zu finden
ist. Und es gibt noch darauf
aufbauend eine erweiterte Form und die 3 würde ich gerne mal
jetzt der Reihe nach mit dir besprechen und.
Um einfach n guten Überblick zu geben und halt auch immer so n
bisschen vor und Nachteile und Use Cases zu nennen.
Und ich glaube dann haben wir hier im.
Vorfeld bevor wir jetzt wirklich in diese 3 Punkte einsteigen,
würde ich vielleicht noch mal ganz kurz n kleinen mini Exkurs
machen. Nur falls weil ich es könnte
sein, dass 2 bestimmte Begriffe fallen innerhalb dieser, wenn
wir das jetzt durchgehen. Und zwar einmal Interface, also
Schnittstelle und abstrakte Klasse, weil wir sind ja jetzt
wie wie du schon meintest, in Objektorientierungsebene und
damit man einmal vielleicht noch mal ganz kurz diesen ne, dass
man dann vielleicht noch mal alle abholt, bei denen es
vielleicht mal so n bisschen ins Grübeln kommt, so was war noch
mal ne Schnittstelle und das würde ich einmal ganz kurz noch
mal sagen und dann können wir direkt reinstarten also n
Interface ist im Endeffekt ja nichts anderes als eine.
Sammlung von Methodendeklaration also, dass du sagst, OK, du hast
jetzt zum Beispiel bei, wenn wir jetzt bei der Pizza sind bei
dieser ne, wenn wir jetzt von diesem Pizzabeispiel ausgehen,
dass du einfach sagst sowas wie mach Soße drauf, das ist eine
Funktion wo also ne die die da zum Beispiel irgendwie sinnvoll
wäre, weil du musst ja irgendwie Soße drauf machen, ne als
Beispiel und dann hast du vielleicht noch andere, aber du
hast im Endeffekt nur diese leeren Hüllen von Methoden, die
einfach so. Für jede Pizza angewandt werden
müssen und die dann aber für jede Pizza selbst implementiert
werden müssen. Also du sagst nur, das muss
passieren bei der Pizza, also du musst auf jeden Fall Soße drauf
tun, wie genau ist bei dem Interface nicht festgelegt, das
heißt du hast im Endeffekt nur du weißt nur was passieren soll,
aber du weißt nicht genau was passieren soll.
Also im Einzelnen. Und wenn du jetzt sagst, du hast
eine abstrakte Klasse, das ist ja ein bisschen ähnlich, kannst
du ähnlich verwenden, nur dass eine abstrakte Klasse zwar auch
sowas haben kann, wieso eine abstrakte Methode wo du sagst
okay es gibt keine Implementierung dafür, aber es
muss implementiert werden in der entsprechenden Klasse, aber es
gibt auch konkrete Methoden, also wo wirklich eine
Implementierung drin ist. Und wenn du jetzt zum Beispiel
das Gleiche mit einer Pizza machst kannst.
Könntest du zum Beispiel sagen, wenn du dieses Interface Pizza
hast, wo du sagst paktros Soße drauf, dann müsstest du, wenn du
2 verschiedene Pizzen implementiert, also
implementierst müsstest du bei jeder Pizza sagen okay pack mal
bitte Soße drauf, zum Beispiel eine Kelle und bei der anderen
zum Beispiel auch eine Kelle oder 2.
Wenn es mehr oder weniger sein soll, wenn du eine abstrakte
Klasse nimmst und dieses in dieser abstrakten Klasse, dass
die Methode packsoße drauf hast, dann.
Dann könntest du immer festlegen, weil wir auch vorhin
meinten, es ist immer die gleiche Menge.
Sagst du dort einfach, mach mal eine Kelle Soße drauf in dieser
Methode und dann kann quasi eine Salami Pizza kann dann im
Endeffekt eine Pizza sein und je nachdem ob es dann ein Interface
ist oder eine abstrakte Klasse, von der ich sag mal die
entsprechende spezifische Pizza ableitet oder erbt.
Hast du dann sozusagen die Möglichkeiten zu sagen, OK, muss
ich das immer selbst implementieren oder ist es
vielleicht schon an der einen oder anderen Stelle schon
vorimplementiert? Ja, also den Unterschied
zwischen Interface und der abstrakten Klasse sehen wir dann
auch in den Factory Pattern auch noch mal genau explizit sag ich
mal, weil das ist nämlich genau der Unterschied zwischen so
einer einfachen Factory und sag ich mal dem offiziellen Factory
Pattern. Ja, aber ja, es ist natürlich
ein wichtiger Unterschied und auch nicht so trivial, aber.
Also für also wenn man selbst halt manchmal so denkt, ja, ist
ja klar was n Interface ist, was ne abstrakte Klasse ist.
Nein, so klar ist das nicht gerade am Anfang nicht.
Deswegen gut, dass du es noch mal erwähnt hast.
Und ich weiß nicht, wie es bei dir ist.
Jedes Mal, wenn ich drüber nachdenke, muss ich auch erstmal
wieder drüber nachdenken. Also es kommt nicht so wie aus
der Pistole geschossen, dass ich sage ja, hier das und das,
sondern erstmal noch mal kurz im Kopf differenzieren und dann
quasi versuchen zu erläutern, das ist nämlich gar nicht so
trivial am Ende. Ich find was man sich auf jeden
Fall merken kann ist n Interface, da steckt niemals
Logik drin. Es sagt immer nur, was muss
passieren, aber nicht, wie es passieren muss.
Und bei einer abstrakten Klasse kannst du beides machen.
Du kannst einmal auf der einen Seite sagen, OK, was muss
passieren und du kannst aber auch noch zusätzlich sagen, wie
soll es denn genau konkret passieren, so das ist so n
bisschen das eigentlich das was man damit machen kann.
Also ich würde sagen ne abstrakte Klasse ist halt
mächtiger als n Interface. Ja genau, also in Interface kann
man sich halt merken, ist halt so ne Art Vereinbarung, sagen
wir es mal so, also es ist halt ne Definition.
Damit beide Seiten, die das verwenden, also der es erzeugt
und der es verwenden möchte, weiß, was drin sein wird.
So ne OK, aber dann lass uns direkt mal mit dem ersten Anfang
und zwar mit der simple Factory, weil da kommen jetzt auch
genauso die Interfaces zum Einsatz.
Also wie gesagt noch mal die Anmerkung, Es ist kein
offizielles Pattern, aber es ist sehr verbreitet und gerade am.
Anfang eines Projekts sehr einsteigerfreundlich, wenn man
so schon mal n bisschen was strukturieren will, aber
vielleicht noch nicht so ne Riesenkomplexität drin hat, dass
es nicht mehr ausreicht. Deswegen ist es eigentlich immer
n ganz guter Start damit anzufangen und man kann sich das
so vorstellen, dass man jetzt dieses simple Factory hat, also
eine zentrale Klasse. Die eine Methode bereitstellt
beispielsweise eine Create mit einem Eingabeparameter, also zum
Beispiel, wie wir bei der Pizzeria hatten, zu sagen, man
kippt noch rein, welche Pizza ja zum Beispiel als String kann man
ja machen. Ja, wenn du jetzt einfach sagen
möchtest Salami oder oder ne Nummer vom vom vom vom Menü
sozusagen und daran wird dann quasi entschieden was erzeugt
wird, das heißt diese Create gibt dir dann am Ende dein
Objekt zurück, was du haben möchtest, oder?
N anderer, n anderes Beispiel ne, was ich auch schon oft
gelesen hab und das macht auch Sinn, wenn du dir jetzt so zum
Beispiel vorstellst, du gehst Fastfood essen, ja du gehst
jetzt zu mcdonald's zum Beispiel, dann stellst du dich
ja auch an die Kasse und sagst ich hätt gern n Cheeseburger so
das wird aufgenommen. Der Satz Ich hätte gerne einen
Cheeseburger ist klar, die Küche weiß, was zu tun ist.
Ja, zum Beispiel jetzt und so. Factory mcdonald's Kitchen ruft
die Create auf und sagt Cheeseburger so, dann geht es in
der Küche zur Sache. Dieser Cheeseburger wird
hergestellt und zwar ist es und jetzt kommt ein Interface, ganz
klar wie n Cheeseburger auszusehen hat.
Ja also dieses Interface wurde für den Cheeseburger
implementiert, das heißt Brötchen keine Ahnung Patty.
Was kommt da? Kommt da überhaupt noch ne Gurke
drauf, keine Ahnung, klar das war da glaub ich noch nie drauf.
Nee, OK. Ja, Käse klar, Käse Käse wär gut
beim Cheeseburger. Ich hoffe, dass da Käse drauf
ist. Weißt du zugeklappt eingepackt
raus, du kriegst das und hast deinen wunderbaren Cheeseburger.
Vorteil an dieser Implementierung ist, dass es
halt schnell, einfach und übersichtlich erstmal ist.
Ne, weil du hast dann diese eine Funktion und du kannst dir
tausende Cheeseburger erstellen, damit ne du sagst ihn immer
wieder. Das hatte ich gerade gesagt.
Ja, mcdonald's Kitchen Punkt create gibt es Cheeseburger als
Parameter rein und du kriegst n Cheeseburger so der Nachteil ist
ist genau das was du nämlich jetzt gerade gesagt hast.
Aber jetzt möchte ich aber n normalen Hamburger jetzt möchte
ich oh Mann jetzt komm ich ins Schwimmen was gibt es bei
mcdonald's? Ja super super Mcchicken oder
wie die heißen ja also es gibt halt ziemlich viele Burger.
So, und da kommt nämlich dann der Nachteil, weil wir auch bei
den Getränkeautomaten meinten, man kann das ja zum Beispiel mit
einem Switch machen, nur dann kommst du halt relativ schnell
bei steigender Komplexität in die Switch.
Hölle also weil du einfach alle Fälle.
Sauber unterscheiden musst, weil du ja immer explizit diesen
einen Burger rausgibst und dieser eine Burger implementiert
quasi deine Schnittstelle wie es aussehen soll und definiert.
Das ist n Cheeseburger, das ist NN Big Mac gibt es n Big Mac so
Big Mac oder oder oder n Chicken Burger oder so ne ich find das
heißt. Ich muss das jeden type erkennen
ne also ich find es gut, dass du sagst auch es gibt n Burger
raus, weil am Ende sagst du ja ne irgendwie die Küche.
Create und dann zum Beispiel Cheeseburger, Hamburger oder was
auch immer. Was am Ende rauskommt ist ja ein
Burger, ne, du sagst ja du kriegst einen Burger und was
aber quasi der also du kriegst n Cheeseburger oder n Hamburger
der aber im Kern n Burger ist ne und wenn wir jetzt zum Beispiel
davon ausgehen, dass wir dann am Ende n Interface, also Burger
ist n Interface und du kannst halt sagen ja OK, der
Cheeseburger muss halt alle Methoden vom vom Burger quasi
implementieren. So, das heißt du weißt auf jeden
Fall auf einen Cheeseburger kommt, also dafür brauchst du
Brötchen, dafür brauchst du ein Patty, dafür brauchst du Soße
zum Beispiel und das ist bei einem Hamburger genauso.
Du brauchst auf jeden Fall auch wieder ein, also ein Brötchen
und du brauchst auch wieder ein Patty und du brauchst auch Soße,
es ist vielleicht was anderes je nach Burger und das ist halt
genau dann sozusagen. Dass du zwar sagst, OK, das muss
alles da sein, aber es muss einzeln implementiert werden in
den entsprechenden expliziten Klassen dann ne, also der
Cheeseburger weiß nur was passieren muss, aber wie genau,
das musst du im Cheeseburger festlegen.
So ne genau. Und da haben wir nämlich genau
das Problem. Wenn du jetzt sehr viele Burger
hast. Ja, also ich find das mcdonald's
Beispiel ist gar nicht so schlecht, weil das kann man sich
auch gut vorstellen, weil es noch n bisschen komplexer ist
als ne Pizza sag ich mal. Also komplexer im Sinne von der
Variantenvielfalt. Wenn du jetzt nämlich wirklich
grundverschiedene Burger hast und du gehst, aber das mit so
einem simple Factory Pattern Ansatz so wirklich ganz simpel
gehalten mit einfach so einer create Methode, ja dann hast du
halt das Ding, dass du wie du meintest, das Interface immer
neu implementieren musst. Ne, wie wird dieser Burger
hergestellt? Na ja, ich brauch das Brötchen
OK ich hol mir das Brötchen. Was brauch ich jetzt für n
Patty? Ja, Chicken Beef gibt es noch
was drittes? Nee ich glaub die beiden so, da
musst du da schon mal entscheiden ne und das muss ja
jeder Bürger für sich implementieren, damit der am
Ende dem entspricht wie er gedacht ist.
Sozusagen ne richtig und da merkt man schon das ist doch
viel doppelte Arbeit, ja. Wieso soll ich komplett neu
definieren, wie n Cheeseburger aussieht?
Wenn n. Hier gibt es doch auch so mit
Jalapenos so ne Chili cheese sag ich mal ne wenn der doch
eigentlich der gleiche Burger also geh ich jetzt mal von aus
der gleiche Burger ist nur, dass du nur noch n paar kleine
Jalapenos da drauf legst. Weißt du da muss ich das doch
nicht komplett neu definieren, wenn das der der gleiche Burger
eigentlich im Kern ist. So und da merkt man schon hm.
Das skaliert doch nicht. Also wenn ich jetzt wirklich ne
riesen burgerkarte hab, das wird nicht skalieren so ne und da ist
nämlich dann auch der Nachteil bei der Simple Factory, dass man
sagen kann, bei wenig Variantenvielfalt ist es schnell
und einsteigerfreundlich implementiert und ausreichend
völlig okay zu starten, weil Stichwort refactoring wenn du
merkst, ah nee, irgendwie mill ich meinen Code jetzt doch zu,
also das ist jetzt anstrengend, da diese ganzen Cases zu
unterscheiden, dann kann ich ja immer noch.
Refactan und vielleicht auf das eigentliche Factory Pattern
kommen und das würde ich jetzt gerne mit dir besprechen, um
einfach auch da mal den Unterschied zu zeigen und
welchen Mehrwert es bringt, auch wenn es natürlich Anmerkung
nicht ganz so einsteigerfreundlich ist, weil
es einfach ein bisschen mehr Aufwand hat.
Ja, also bisschen mehr Overhead an Code hat am Anfang ja ja auf.
Jeden Fall. Also wenn ich jetzt zum Beispiel
dieses Factory pattern, so wie es vielleicht dann auch
angedacht ist, nehme. Würde ich einmal kurz vielleicht
direkt den Unterschied zum zum simple Pattern mit dem Burgern
darstellen? Ne, weil wenn du dir jetzt zum
Beispiel überlegst, du hast in in diesem Burger, den du haben
möchtest, du meintest ja Cheeseburger und Chili
Cheeseburger ne, also es klingt ja schon fast gleich und bei dem
wenn wir jetzt noch mal dieses dieses Beispiel mit dem
Interface haben, dann steht ja in in dem Interface drin, du
brauchst ein Brötchen. So, und dieses Brötchen musst du
ja dann sozusagen im Cheeseburger definieren.
Also ne, du brauchst ein Brötchen, musst du da in ne
Logik reinpacken wie zum Beispiel Return?
Weiß nicht simple Bun oder so ne, also ein ganz normales
Brötchen und das gleich diesen gleichen, exakt gleichen Code
musst du ja noch mal im Chili Cheeseburger definieren, das
heißt du hast ja eigentlich quasi ne Code dopplung, die du
eigentlich nicht doppelt brauchst.
So und das bringt aber nun mal jetzt sozusagen so ein Interface
mit sich, wenn du sozusagen ne Factory über so ein Interface
nutzt, ne? So ein simple Factory.
Wenn du jetzt aber wirklich diese diese Factory patter
nimmst und sagst an der Stelle okay wir nehmen jetzt aber eine
abstrakte Klasse an dieser Stelle, dann können wir bei
einem sagen du hast einen Chili Cheeseburger und du hast einen
Cheeseburger und das Ganze hat eine abstrakte Klasse, von der
geerbt wird sozusagen, die ist einfach ein Burger und dieser
Burger hat nimm ein Brötchen und ich.
In dieser Burger Klasse, in dieser abstrakten Klasse ist
schon definiert, dass du für deinen Burger, für die also
einmal den Cheeseburger und den Chili Cheeseburger jeweils das
normale oder das einfache Brötchen nimmst.
Und damit hast du diese Implementierung schon in der
abstrakten Klasse drin und musst es nicht zweimal im Cheeseburger
und im Chili Cheeseburger sozusagen implementieren.
Und das hilft dann halt sozusagen bestimmte.
Eigenschaften schon zusammenzufassen, um halt eben
diese Codeduplikation zu vermeiden.
Wie du meintest, weil stell dir vor, du hast n burgerrestaurant,
ne was du jetzt in in weiß ich irgendwie programmierst in einem
Game oder so wo immer der Gleiche es sind immer nur die
gleichen Burgerbrötchen ne du hast niemals andere
burgerbrötchen, da macht es keinen Sinn.
In 20 Bürgern beispielsweise wirklich 20 mal den gleichen
Code zu machen. Ich mein, da kommt man ja
relativ schnell hin und denkt sich so okay irgendwie müsste
ich das ja vielleicht vereinheitlichen können.
Genau, nimm ne abstrakte Klasse und kein Interface an der Stelle
um das jetzt mal so direkt im Vergleich zu sehen, ne.
Genau. Und dann dann quasi alle, die
dann so richtig auf Vererbungen in der Objektorientierung
stehen, die können das natürlich bis auf die Spitze treiben, dass
du sagst, ich hab ne klasse Burger, die ist abstrakt, ne und
dann gibt es n Cheeseburger und den kann ich auch noch mal
weiter vererben zum Chili Cheeseburger, der eigentlich nur
n Cheeseburger ist, wo ich am Ende halt wie gesagt noch
lalapenos drauf mache oder irgendeinen anderen Burger, wo
auf einmal Salat und Tomate drauf ist oder irgendwie so.
Also du kannst das ja immer weiter Kapseln sozusagen und das
Factory Pattern dann halt so richtig ins Spiel bringen, sag
ich mal. Aber ich find n anderes
Gedankenspiel dabei auch noch gut, um sich das noch mal
vorzustellen, wofür so n Factory Pattern auch gut ist.
Wir haben ja jetzt gesagt, du hast n burgerladen ja,
mcdonald's als Beispiel, jetzt ist mcdonald's vielleicht sehr
standardisiert. Länderübergreifend, so wie ich
es jedenfalls kenne. Also wahrscheinlich wird es
schon Unterschiede geben, auch wahrscheinlich in den, es ist ja
irgendwo n Franchise am Ende, das heißt du hast wahrscheinlich
auch n bisschen andere Karten oder Aktionen whatever aber es
ist schon so standardisiert, dass ich glaub ich würd ich
jetzt mal sagen, so n cheeseburger.
In fast jedem Land gleich ist ne.
Das heißt, das wäre ja auch wieder so n bisschen Richtung
Simple Factory, auch wenn es halt wie gesagt zu viele
verschiedene Burger gibt, aber da würde das ja noch so halbwegs
funktionieren zu sagen, Hey Cheeseburger ist doch immer
gleich, ja brauch ich es auch wirklich nur einmal machen, aber
wenn man das n bisschen allgemeiner formuliert und ich
hab jetzt einfach n Burger ne Burger Kette oder n Burger laden
ne wo ich einfach gut Burger essen gehen kann ja dann sieht
ja dieser Laden oder? Sagen wir mal so, ich möchte
einfach einen Burger bestellen und ich gehe jetzt in
verschiedenen Ländern in einen entsprechenden Laden und kaufe
mir einen Burger, dann sieht er ja natürlich beispielsweise im
asiatischen Raum anders aus als im in der USA zum Beispiel ja,
in der USA ist die Wahrscheinlichkeit ja schon
groß, sowas Big Mac Artiges zu bekommen.
In im asiatischen Raum wahrscheinlich eher irgendwas
asiatisch angehauchtes, ja vielleicht irgendwie so mit
tiriyaki Soße in Japan oder so. Keine Ahnung, was geiles halt so
ne, aber am Ende sind beides Burger, sind aber grundlegend
verschieden. Also wie willst du jetzt
anfangen mit einer simple Factory das alles abzubilden?
Das heißt da kommst du halt jetzt zu den offiziellen Pattern
zu sagen es gibt ne abstrakte Burgerklasse ne es gibt
Grundeigenschaften eines Burgers, aber je nach Land.
Sind die Spezifikationen obendrauf anders?
Ja, für diesen Burgerladen, das heißt, meine Factory ändert sich
dementsprechend auch oder die Burger, die ich damit erstellen
kann, dass ich zum Beispiel sagen kann, hey, ich hab ne
Factory und ich möchte jetzt n Burger und ich bin in Japan zum
Beispiel und dann kriegst du halt deinen teriyaki Burger, ja
oder ich sag, ich bin jetzt in der USA und Du kriegst halt n
Big Mac so aber unter der Haube sind das abstrakte Burger, die
selbst implementieren zum Beispiel deine Big Mac Klasse
Teriyaki Burger Klasse. Ich hab keinen besseren Namen,
sorry, und da hast du jetzt den Vorteil, dass die eigentliche
Erstellung ja wie das Objekt am Ende aussieht, dann in deinen
Subklassen ist. Das heißt, die Factory hat jetzt
nicht mehr die Logik sowas wie OK, das Interface ich returne
jetzt das Interface mit den und den Funktionen oder den und den
Werten ja, sondern ich geb jetzt ne Subklasse zurück wie Big Mac
Burger. Ja, weil die Factory wurde jetzt
aufgerufen, mit Burger in der USA, Mhm so und dann geb ich ne
Big Mac Klasse zurück und die Klasse selbst definiert jetzt
wie der Burger ist und nach außen ist es dann halt wirklich
nur noch dieser abstrakte Burger.
Erstmal ja so und das ist halt der große Vorteil, dass du halt
so komplexe Abläufe damit dann auch implementieren kannst.
Zum Beispiel sowas wie. Länderabhängig Länderabhängig
ist, weißt du ja. Ich meine, das ist ja, wenn man
sich das zum Beispiel noch mal im Vergleich vorstellt, und du
hast jetzt ein bisschen ein leicht abstrakteres Beispiel, du
hast jetzt zum Beispiel ein Interface, ne, weil du ja
meintest, das macht damit nicht so viel Sinn und stell dir vor,
du hast am Ende ein Interface, wo alle Objekte eigentlich nur
eine Methode teilen, die sie auf jeden Fall alle haben, und dann
aber zum Beispiel Objekt 1, ne, was du instanzieren möchtest.
Hat dann aber 5 Funktionen von der von dem Interface noch und
klasse 2 noch mal 5 andere. Das heißt du hast in deiner in
deinem Interface 11 Funktionen, aber für die eine Klasse
brauchst du eigentlich nur die Hälfte und für die andere auch n
bisschen mehr als die Hälfte. Du hast also ne minimale
Schnittmenge und denkst dir so, warum hab ich eigentlich n
Interface mit so vielen Funktionen die ich aber am Ende
gar nicht implementieren muss? Also du musst sie quasi
implementieren, was sind leerimplementierungen dann und?
Und du denkst ja so, die brauch ich da ja gar nicht drin.
Ne und das macht es dann an der Stelle irgendwann einfach nicht
mehr sinnvoll, sozusagen so n simple Factory Pattern zu
verwenden, sondern dann halt eben dieses Standard Factory
Pattern zu nutzen. Ne und ich find das ja, wenn wir
jetzt das Ganze noch mal vielleicht n bisschen
technischer erklären, weil mir bringt das manchmal auch
irgendwie was, wenn ich mir dann denke so OK, ja gut, wann
implementier ich denn jetzt mal ne ne Burger factory, weißt du?
So, wo wird denn das? Überhaupt, ich hab jetzt genug
über Burger geredet, ich hab erstmal Hunger, nur Pause ein.
Aber zum Beispiel, wenn man jetzt sagt, du hast einen.
Ich bestell auch Grad nebenbei. Was willst du auch was?
Ja komm. N.
Cheeseburger und n Chili cheese würde ich gerne lesen.
Wenn du jetzt aber pass auf wenn du jetzt sagst du hast ne UI
oder so ne und du sagst ich möchte jetzt du hast ne Factory
wie wie du sie gerade beschrieben hast.
Mit einem Button so und dann möchtest du einfach nur zum
Beispiel einen Button haben und jetzt ist aber die Frage, auf
welchem Betriebssystem hältst du dich denn gerade auf, weil jeder
weiß das ja, dass zum Beispiel auf einem Mac das Ganze
vielleicht ein bisschen anders aussieht als auf einem Windows
PC, die UI oder vielleicht auch bei einem Linux oder?
Und damit du dann aber im Endeffekt sagst, ich möchte nur
diesen Button, aber unabhängig davon, also ich möchte ja gar
nicht, mir ist es egal welche auf welchem Betriebssystem ich
mich befinde, diese Factory soll mir einfach den richtigen Button
zurückgeben, den ich dann einfach meine UI einsetzen kann.
Ja, das ist ein gutes Beispiel, weil ja der Button unabhängig
vom Betriebssystem am Ende die gleiche Funktion haben wird oder
die gleichen Fähigkeiten. Attribute nenn ich es mal ne.
Aber ich natürlich im Betriebssystem Style bleiben
möchte. Gerade wenn ich jetzt so Cross
Plattformen entwickle. Ja und ich sage, ich habe jetzt
zum Beispiel ne Desktop application und ich möchte die
aber auf eingängigen Betriebssystem anbieten können,
dann macht es natürlich Sinn wie du gerade meintest erstmal zu
gucken auf welchem Betriebssystem läuft diese
Anwendung und dementsprechend Style ich sie oder baue sie wie
auch immer an welchem Step wir jetzt sind ja und?
Das ist halt n cooles Beispiel, weil unter der Haube ist es ja
der gleiche Button. Am Ende ne, der hat dann zum
Beispiel irgendein Callback, wenn du ihn drückst der
implementiert werden kann und das hat ja bei allen
Betriebssystemen nur dass er halt vielleicht vom Styling
anders aussieht. Richtig.
Und dann hast du sozusagen das Styling, ist unterschiedlich in
den eigenen Klassen, aber dieser Callback, wie du ihn zum
Beispiel gerade genannt hast, oder die Funktionalität, die
dahinter steht n bisschen abstrakter.
Ist dann halt eben in der Basisklasse vertreten.
Ne und und weil es ist ja immer das Gleiche dann für diesen
entsprechenden Button, sagst zum Beispiel N submit Button und
dann kriegst du halt wirklich diesen submit Button
unterschiedlich gestylt, je nachdem Betriebssystem aber die
gleiche Funktionalität, ne das ist auf jeden Fall dann der Sinn
dahinter. Das heißt, um das noch mal
technisch sich vorzustellen, man hat dann im Code zum Beispiel ne
Klassenabstrakte Klasse Button und die Implementierung davon
wäre dann zum Beispiel N Windows Button oder N Linux Button.
Ja, und die Factory gibt dir den abhängig von dem Betriebssystem,
auf dem du bist. N Windows Button oder N Linux
Button um es so n bisschen konkreter zu machen.
Und ja da sieht man ja eigentlich schon die die
Vorteile einer Factory. Ja also du hast halt diese
Austauschbarkeit, ne, das heißt mit jeder Subklasse die ich
implementiere kriege ich halt auch so ne neue Implementierung
rein ohne die anderen anrühren zu müssen.
Ganz wichtiger Punkt ja wenn ich das Styling am Linux Button
ändern muss ich nichts am Windows Button machen weil der
soll ja auch bleiben wie er ist. Das heißt, ich muss da am Code
nicht drin rumrühren und kann halt potenziell Fehler einbauen.
Das heißt, die Austauschbarkeit ist halt auch gegeben, ne, wenn
zum Beispiel der Linux Button einfach ganz anders aussehen
soll oder vielleicht gar nicht mehr drin sein soll, oder dazu
kommt, du kannst es halt einfach nebeneinander halten sozusagen,
das heißt es ist auch besser testbar und wartbar ne wenn ich
n Test schreibe für den Windows Button und den Linux Button
änder, dann hab ich halt am Windows Button Test natürlich
auch immer noch grün, hoffentlich am Ende ne wenn ich
es richtig implementiert habe das heißt?
Wir haben halt keinen zentralen Code mehr, der alles wissen
muss, sondern wir lagern es auf die Subklassen aus, was laut
Objektorientiert einfach denn sauber getrennt ist.
Ja, definitiv. Und im Endeffekt.
Also es gibt natürlich auch Nachteile, es ist ja nicht immer
nur so, dass es da die ganze Zeit immer nur ne Vorteil
Vorteil, Vorteil, du brauchst natürlich n komplexeres Setup
irgendwo ne, also du hast natürlich jetzt.
Also dein ganzer Code wird natürlich komplexer an dieser
Stelle, weil du zum Beispiel ne, gerade wenn du sagst, du hast
mehrere Objekte von einer, also die, die zusammengehören zu
einer Familie, ne, dann brauchst du halt so ne so ne basisklasse,
die dir sagt, OK ne, meine ganzen Bürger sind am Ende n
Bürger ne die verschiedenen. Wenn du jetzt aber das ganze
noch länderspezifisch spezifisch aufteilst, dann hast du
verschiedene. Burger, die zum Beispiel keine
Ahnung, amerikanische Burger sind.
Du hast Burger, die aber asiatische Burger sind, ne, und
dann hast du wieder diesen diese beiden Burger Varianten, die
aber am Ende auch wieder nur Burger sind, das heißt du holst
dir natürlich ne höhere Komplexität, ne höhere Tiefe, ne
in deinen Code rein. Und das kann natürlich auch dazu
führen, dass es vielleicht n bisschen schwieriger am Anfang
durchzublicken ist. Ne.
Deswegen heißt das andere ja auch simple Factory, weil es
halt eigentlich eher n bisschen flacher Gehalt, also diese ganze
Hierarchie n bisschen flacher hält.
Aber wie gesagt, hier macht es mehr Sinn, wenn es auch n
bisschen generell, wenn wenn diese ganze Abhängigkeit
komplexer wird, dann also ne mit einer höheren Komplexität steigt
meistens halt auch die Komplexität des Codes.
Ja, es ist natürlich ratsam, immer zu gucken.
Je höher also auch, wenn die Komplexität steigt, Krieg ich es
vielleicht doch mit möglichst wenig Komplexität in meinem Code
hin, aber ab einem ab einer gewissen Ebene kommt man halt
einfach nicht da dazu, dass man halt eine gewisse Komplexität
vermeiden kann. Ja, und das ist auch ein gutes
Stichwort, Komplexität, und das wäre so im Prinzip die dritte
Stufe. Von den Pattern ist dann die
sogenannte Abstract Factory, das heißt, wir fangen jetzt quasi
noch an, uns zu überlegen. OK, ich hab ne Factory und ich
kann jetzt zum Beispiel länderspezifisch den Burger
Design ne, also beispielsweise ich möchte n cheeseburger haben
und der sieht halt wie gesagt in Japan anders aus als in der USA.
So das können wir jetzt schon ganz gut abbilden.
Wie sieht das jetzt aber zum Beispiel aus, wenn wir ganze
Produktfamilien haben und da kommt dann die Abstract Factory
ins Spiel, das heißt, wir haben Produktfamilien, die
Zusammengehörig sind, und das kann man an dem Beispiel, wir
sind wieder bei dem Burger auch wieder gut erklären, weil ich
hab jetzt nicht nur Bock n Burger zu essen, ich fühle es,
ich möchte n Menü haben, ja. Ja.
Und. Habe jetzt quasi Burger, eine
Beilage und ein Getränk. So und das alles natürlich so
wie ich es erwarte im Stil des Restaurants, wo ich gerade
bestelle, ja sagen wir mal zum Beispiel bei einem Cheeseburger
in Amerika kriege ich halt so klassisch Doktor Pepper Cola
keine Ahnung und Fries und in Japan zu meinem Teriyaki Burger
will ich jetzt nicht unbedingt eine Doktor Pepper dazu haben,
sondern ich kriege. Ah, Klischee, auf keiner Matcha
Tee oder so. Weißt du also was ich damit
meine ist, du hast ja im Prinzip die Menüs die angeboten werden
von dem Restaurant sind natürlich auch spezifisch und im
Stile ihres Restaurants ja also. Da, das wird sich ja denn
grundlegend als gesamte Produktfamilie Burger Menü
unterscheiden und da kommt halt denn die Factory ins Spiel, die
Abstract Factory, die dann wiederum deine Factory so
definiert, zum Beispiel, dass du sagst, ich bin in Japan oder in
der USA und dafür sorgt, dass die einzelne Produkte, die jetzt
ne Factory intern bereitstellen kann sowas wie gib mir einen
Burger, gib mir eine Beilage, gib mir ein Getränk.
Dafür sorgt, dass es in sich zur gleichen Produktfamilie gehört,
dass ich halt nicht sage, ich Krieg n amerikanischen Burger
und ne japanische Beilage zum Beispiel, das wär auch Wahnsinn,
das wär Wahnsinn, das nennt man Fusionsküche.
Fusionsküche genau, aber weißt du, wie ich meine?
Und ich finde, da kann man das eigentlich ganz gut dran
erkennen, denn oder beziehungsweise verstehen, warum
man diesen Schritt auch noch. Geht ja.
Wenn wir jetzt zum Beispiel noch mal dieses UI Beispiel von
vorhin nehmen, ne und das noch zum Beispiel auch noch mal daran
erklären, noch mal in die Technik n bisschen so
abzutauchen ein wenig, dann ist es ja so, dass du zum Beispiel
sagst, ich möchte jetzt ein, also meine UI Elemente haben,
ne. Also nicht nur einen Button,
sondern ich möchte vielleicht auch noch eine Checkbox haben
oder ich möchte was gibt es noch einen Radio Button haben oder
was auch immer, so verschiedene Elemente, die aber auch wieder
logischerweise entsprechend gestylt sind.
Du kriegst ja nicht einen Mac Button in Windows Checkbox und
eine Linux Radio Button, das wird ja im Endeffekt, also
kannst du auch machen, wäre aber irgendwie blöd.
So, und dann ist es halt im Endeffekt so, dass du halt
abhängig vom Betriebssystem dir diese Familie holst.
Von Ui Elementen, von denen du dann wiederum ein spezifisches
brauchst. Und im Endeffekt kann man sich
das so vorstellen, dass Du eine Factory hast, die anhand des
Betriebssystems und also unterscheidet, wenn.
Welche Factory sie dir gibt, um den entsprechenden Einzelnen,
das einzelne Ui Element zu bekommen.
Das heißt du hast eine Factory die dir eine Factory ausspuckt,
die dir dann am Ende wieder ein Objekt gibt.
Genau also im Prinzip. Das ist ein gutes Beispiel, und
wenn wir jetzt noch mal so auf auf die Ui Elemente gehen, du
definierst ja nicht jedes Mal. Also du, du erzeugst dir jetzt
ja nicht eine Factory für Buttons und sagst jedes Mal wenn
Du einen Button haben möchtest übrigens Windows.
Und jetzt gib mir noch ne Checkbox.
Übrigens Windows ja und dann machst du irgendwann den Fehler.
Übrigens Linux. Ach verdammt weißt du und
deswegen gehst du quasi diesen Weg mit der Abstract Factory und
sagst gib mir ne UI Factory Windows und die kann dir jetzt
sagen create Button, create checkbox und es wird immer.
Windows sein am Ende, weil du das unter der Haube quasi so
definiert hast. Und dann musst du dir bei der
Anwendung oder bei dem Erstellen der Objekte darüber keine
Gedanken mehr machen und das bringt halt mehrere Vorteile mit
sich. Also erstmal, es ist konsistent,
ja wie du gerade meintest, es passt alles zusammen,
beispielsweise wenn ich betriebssystemabhängig bin.
Es ist super testbar. Ich kann die einzelnen
Betriebssystem Stylings abtesten es ist austauschbar, ne, weil es
muss ja nicht nur Betriebssystem abhängig sein, so ein
klassischer Anwendungsfall sind ja auch so Themes sage ich mal
ne habe ich ein helles Layout, habe ich ein dunkles Layout und
ich möchte ja nicht bei jedem UI Element sagen, übrigens du bist
gerade ein dunkles Layout oder ein helles Layout nein du willst
es ja global irgendwo entscheiden und dann einfach
darauf arbeiten sozusagen oder wenn du eine Testumgebung
erzeugen willst dann. Willst du ja auch sagen, gib mir
mal meine Test Factory, ich will jetzt da was ausprobieren, zum
Beispiel also das das bringt halt viele Vorteile mit sich
schnell austauschbar auch zu sein.
Ja Nachteil glaube ich kann man eigentlich ganz schnell erklären
oder komplex. Ja klar, das ist natürlich die
komplexeste Variante von allen Factories.
Und wie gesagt, ich ich persönlich würde auch darauf
verzichten, wenn es nicht notwendig wäre, ne, also diese
dritte Variante. Was ich noch sagen würde ist,
weil das ist zum Beispiel auch n Punkt, der hat sich früher
irgendwie ganz am Anfang von meinem Studium.
Zum Beispiel hat sich auch nicht so richtig erschlossen und ich
würd das auch vielleicht noch mal so, weil ich denk mir so,
vielleicht hat man mal das Problem gehabt, was vielleicht
andere auch haben oder das Verständnisproblem, man kann
sich ja jetzt hinstellen und sagen, was bringt denn
eigentlich so ne Factory, wieso sag ich jetzt zum Beispiel nicht
einfach ey, dann erstelle ich mir n neues Objekt davon und
dann mach ich damit was und da an einer anderen Stelle nehm ich
mir halt n anderes Objekt. Ne was ich da halt vielleicht
brauche und dann mache ich das halt ne, weil du ja meintest am
Anfang um noch mal den Bogen zum Anfang zu schießen.
Du hast dann überall mal New Objekt von dem New Objekt von
dem mach mal dies mach mal das ne und wenn du dir jetzt zum
Beispiel vorstellst du hast n ne Anwendung auf deinem eigenen
Server laufen und du sagst zum Beispiel OK ich möchte aber
diesen Server, also ich möchte meine Anwendung überwachen und
du hast jetzt zum Beispiel du fängst an und sagst OK ich
möchte jetzt. Diese, wenn irgendein Problem
auftritt, möchte ich zum Beispiel mich selber
notifizieren, ne mit einer e Mail so dann mach ich, erstelle
ich irgendwie mir so NE Mail notifier und sag send mal die
notification raus über die e Mail ne so und dann hast du aber
vielleicht irgendwann denkst du dir so oh e Mail wirklich, das
ist einfach da ich ich guck nicht immer so oft in die e
Mails ich brauch das vielleicht als SMS oder so ne so das heißt
du sagst ey ich erstell mir jetzt noch n.
Weiteren Notifire, nämlich einen SMS notifire und sende dann
sozusagen noch als SMS raus. So, und wenn du jetzt aber
irgendwann sagst, weiß nicht SMS, ich habe manchmal irgendwie
bin in einem Funkloch, aber Internet habe ich irgendwie, ich
brauche das auch noch für eine App als push Nachricht, dann
machst du noch einen Push notifire so ne, dann hast du 3
verschiedene Notifire, die du aber alle in diesem wenn jetzt
zum Beispiel ein Fehler in deinem in deiner Anwendung
auftritt, möchtest du über alle notifire dich notifizieren,
damit du auch wirklich mitkriegst.
Es ist ein Fehler aufgetreten im System ne.
Und egal, wo du dich gerade aufhältst, entweder du hast kein
Internet oder du hast einen Netzausfall oder du hast gerade
keine Ahnung, mal wieder nicht in die e Mails geguckt, irgendwo
willst du es halt herkriegen diese Information und dann
möchtest du deinem Code aber nicht sagen, create new e mail
notifeier und sende create new SMS notifeier und sende create
new push notifeier und sende ne, das müsstest du ja für jeden,
für jedes immer wieder noch mal neu machen.
Und wenn du jetzt aber sagst, ein e Mail notifier und eine SMS
Notifier und Push notifier sind alles irgendwo notifier ist
jetzt egal welche Factory an der Stelle und wie das genau
implementiert ist. Aber du kannst dann zum Beispiel
wenn du noch ein Notifier hinzufügen möchtest, kannst du
alle in eine Liste von Notifier packen und dann mit einer vor
darüber gehen und einfach sagen okay notifier send so, das heißt
du hast einen viel eleganteren Code am Ende als immer zu sagen.
Also du musst natürlich diesen Notifire dann über deine Factory
die entsprechenden Notifire erstellen und einen neuen
hinzufügen. Du musst aber nicht jedes Mal
sagen okay, ich mache das jetzt für jedes erstelle ich ein neues
Objekt und so weiter und sofort, sondern du nutzt immer nur die
Factory sagst du möchtest ein bestimmtes neues Ding haben,
kriegst es dann packst es in die Liste und wenn du jetzt zum
Beispiel sagst, du hast eine Liste und in vielen Sprachen die
jetzt auch Typsicher sind, kannst du ja nicht sagen, ich
erstell eine Liste von einem Objekt.
E Mail notifire von dem Objekt SMS Notifire und von dem Objekt
Push notifire weil es sind 3 unterschiedliche Objekte.
Wenn du aber sagst das sind alles notifire, dann kannst du
ne Liste von Notifirern erstellen und dann darüber
iterieren und das sind manchmal so dann die Vorteile die das
dann am Ende mit sich bringt. So weißt du so Kleinigkeiten wo
ich am Anfang wo ich mir weißt du das ist immer so bescheuert
so am Anfang des Studiums dachte ich dann so was wie ja was
brauche ich das ich verstehe den Anwendungsfall noch nicht und
irgendwann kam ich an den Punkt wo ich mir dachte das ich würd
das jetzt gern alles in eine Liste packen aber es geht nicht
und dann irgendwann kam so diese Connection wo ich mir dachte Oh
ne Factory weißt du und das kann man halt wie gesagt ist
unabhängig vom Typ der Factory kann man mit allen machen, die
Implementierung ist dann sei mal dahingestellt, da haben wir ja
auch schon n paar Beispiele genannt, aber das ist zum
Beispiel finde ich n sehr sehr wichtiges Beispiel um zu zeigen
so kannst du ne Factory nutzen als genau.
Es hält halt den Code schlank, dann am Ende alright.
Genau dann hatten wir ja noch n konkretes Beispiel am Ende dann
würde ich sagen lass uns doch mal noch mal kurz
zusammenfassen, ich kann ja noch mal die meta Analogie Ebene
zusammenfassen, die wir so quasi aufgebaut haben in dieser Folge
also gehen wir noch mal quasi von.
Unserem Burgerladen aus ne also die simple Factory ist ich geh
jetzt hin und bestelle einen einzelnen Burger.
Ja, also wirklich nur ich bin in einem Laden, es gibt nur diesen
Laden, es gibt nur einen definierten Cheeseburger und ich
will n Cheeseburger haben, dann ist klar wie der aussieht und
ich Krieg den ja das erweitert wenn wir jetzt gesagt haben na
ja verschiedene Köche gleiche Karte aber unterschiedlicher
Burger ne also ich kann jetzt bei verschiedenen Köchen.
Einen Cheeseburger bestellen und der wird halt unterschiedlich
sein am Ende, weil es ja der unter unterschiedlich zubereitet
wird, sehr wahrscheinlich, da hatten wir ja die
Länderbeispiele genannt und da kommt halt die Factory, das
eigentliche Factory Pattern ins Spiel, dass man sagt, gut, wir
haben jetzt abstrakten Burger und der wird jetzt in den
Subklassen definiert Cheeseburger und so sieht er aus
und jeder implementiert sich seinen Cheeseburger, sozusagen
ne und dann abhängig davon wo ich bin, kriege ich dann
dementsprechend den Cheeseburger und die Abstract Factory.
Die maximale Ausbaustufe, sag ich mal, ist halt das
Menübeispiel. Wenn ich jetzt n komplettes Menü
haben möchte, dann krieg ich halt auch entsprechend immer
passend Beilagen und Getränke beziehungsweise ich kann denn
nur auswählen, was passend für den Laden dazu ist.
Ja, also wie sieht das Burger Menü da aus?
Genau. Und das ganze n bisschen
technisch. Kannst du es noch so n bisschen
einordnen wo du was so ungefähr verwenden würdest?
Zum Beispiel? Wir hatten es ja jetzt auch so
in der Folge n bisschen angeschnitten.
Ja, also simple Factory, ne, da hat man hat man eher zum
Beispiel so n Interface was man verwendet für kleinere Projekte
vielleicht Tutorials ne wenn man jetzt nicht so viele Varianten
von Objekten von von von einem Typ hat, beispielsweise das
Factory Pattern jetzt beispielsweise.
Wenn man dann mehr Objekte, wenn es komplexer wird, man halt
mehrere Objekte hat, die vielleicht auch noch in Klassen
wiederum gegliedert werden können, ne und also wie jetzt
zum Beispiel halt ne, was du ja auch gerade beschrieben hattest
mit deinen Beispielen und wenn du jetzt abstract Factory ne
Abstract factory nimmst, dann bist du halt auf
unterschiedlichen Objektfamilien unterwegs.
Dass du halt sagst, okay. Du kannst erstmal über das
Factory Pattern kannst du dir ein eine bestimmte Familie
überhaupt holen, dass man da gar nicht irgendwie sich vertun kann
und dann ein spezifisches Objekt aus dieser Familie, das heißt du
Filterst im Endeffekt ein bisschen vor, so und ja, dafür
sind eigentlich die Sachen ganz gut gedacht, wie gesagt, es ist
ich glaube so ein Abstract Factory.
Habe ich zum Beispiel selber noch gar nicht verwenden müssen,
weil es ist auch immer die Frage, wann braucht man das
wirklich. Es ist, es ist ratsam, so was
irgendwann mal einfach spaßeshalber zu programmieren,
um es mal gemacht zu haben, aber das bedeutet noch lange nicht,
dass es unbedingt wichtig ist, das anzuwenden, ne, aber wenn du
jetzt zum Beispiel sagst simple Factory und Factory Pattern,
diese beiden würde ich zum Beispiel schon als sehr
hochfrequent einordnen und das ist durchaus wirklich wichtig,
dass man auch dann. Das versteht und das auch
anwenden. Kann also.
Die Abstract Factory ist sehr wahrscheinlich oder oftmals
nicht notwendig selbst zu implementieren, weil man ja auch
oft auf Frameworks und Libraries zurückgreift, die das unter der
Haube implementieren. Gerade so in der Cross Plattform
Welt wird das ja dir quasi genau diese Sachen werden die ja
abgenommen dann am Ende ne, weil das halt unter der Haube so
implementiert wurde. Aber das wäre auch so.
Ich würde gerne noch so ein 2 Tipps oder jeder ein Tipp kann
man am Ende noch mitgeben so bevor ich die Folge schließe
sage ich mal, das wäre nämlich auch genau mein Tipp gewesen,
was du gerade angeschnitten hast.
Ist liebe Zuhörer, liebe Zuhörer, falls du dich mit dem
Factory Pattern noch nicht so auseinandergesetzt hast oder
immer noch ein bisschen struggles, weil du vielleicht
gerade am Anfang der Softwareentwicklung stehst,
probiere es aus, nimm dir die Beispiele unserer Analogien wie
zum Beispiel mcdonalds oder dem Burgerladen allgemein oder die
Pizzeria oder. Und Programmier damit mal
einfach n factory pattern, sag dir, ich mach jetzt n simple
Factory, dann refactor ich das zum Factory Pattern zum Beispiel
und ich probier auch mal ruhig n Abstract Factory aus, damit ich
es einfach mal gemacht hab, dann sieht man einfach, welche coole
Möglichkeit dieses Pattern bildet oder bietet um Code zu
strukturieren. Ja, auf jeden Fall.
Und wie gesagt, am besten immer. Kleinen anfangen, sich dann wie
du auch eigentlich meintest ne du hangelt, man hangelt sich
einfach von der einen Factory zur anderen durch und ich würde
auch einfach mal wirklich sagen OK wenn man das gemacht hat und
diese Factory gebaut hat würde ich noch mal sozusagen daneben
legen. Das gleiche Beispiel was du
gebaut hast und keine Factory verwenden um einfach mal genau
gegenüber zu diesen diese Gegenüberstellung zu haben.
Wie sieht es denn mit aus und wie sieht es ohne aus und was
gefällt mir besser und die Antwort liegt nach dieser Folge
eigentlich auf der Hand. Ja.
Sehr gut. Ich denke, wir haben es sehr
umfangreich besprochen, da sieht man mal, dass man zu so einem
Designpattern echt viel erzählen kann, gerade wenn man damit mal
so n bisschen Analogien bringt. Aber ganz ehrlich, das hilft
einfach mega das zu verstehen, das hat mir damals geholfen und
ich hätte mir gewünscht, dass mir jemand das mal so anhand von
einfachen Beispielen erklärt und deswegen vielen Dank dafür, Fabi
ebenso Liebe zur Liebe zur falls dir die Folge gefallen hat oder
du Anmerkungen hast zu den Pattern oder Fragen, schreib uns
gerne. Alle Links zu den Plattformen
oder auch unsere Podcast Mail findest du in den Shownotes.
Wenn dir der Podcast allgemein gefällt, lass auch gerne ne
Bewertung da, das hilft uns quasi weiter zu wachsen und noch
mehr Leuten unseren Content anbieten zu können und damit
noch mehr Leute davon profitieren können.
Und ja, ansonsten würde ich sagen, hören wir uns alle beim
nächsten Mal wieder. Und lasst euch den Burger
schmecken. Und lasst euch den Burger, ich
geh jetzt Burger bestellen. Und habt ne gute Zeit bis dahin
und bis zum nächsten Mal deine Coding Bodys.
Gemeinsam besser.