C# :: Aufgabe #325 :: Lösung #1
2 Lösungen

#325
Zoo mittels einer Factory-Methode
Fortgeschrittener - C#
von Exception
- 12.09.2020 um 16:36 Uhr
Hallo zusammen,
heute erzeugen wir einen Zoo!
Erzeugt hierfür eine Basisklasse (oder Interface) "Animal" und einige Klassen die davon erben (z.B. "Lion", "Penguin", "Crocodile", "Snake").
Als nächsten Schritt wollen wir nun eine Factory-Klasse erzeugen, die sich am "Factory-Method-Pattern" orientiert.
In dieser Klasse soll eine Methode "createAnimal" existieren, die ein "Animal" zurückgibt.
Welches "Animal" zurückgegeben wird überlassen wir vorerst dem reinen Zufall ;)
Daher kann diese Klasse auch "RandomAnimalFactory" genannt werden.
Lasst nun 200 "Animals" in den Zoo einziehen.
Wie ist die Verteilung der "Animals" einer jeden Spezies in unserem Zoo?
Es kann mit der zufälligen Erzeugung zu einem gewissen Ungleichgewicht kommen.
So fühlt sich ein einzelner Pinguin gegen 199 Löwen sicher etwas in der Unterzahl ...
Erstellt nun eine zweite Factory-Klasse "BalancedAnimalFactory".
Diese soll ebenfalls die Methode "createAnimal" enthalten.
(Macht es nun evtl. Sinn sich auch bei den Factory-Klassen über ein Interface gedanken zu machen?)
Diese Factory soll nicht mehr komplett zufällig Tiere erzeugen sondern etwas ausgeglichener.
Die dort vorhandene "createAnimal" Methode soll wie folgt funktionieren:
Angenommen wir haben vier Tier-Klassen ("Lion", "Penguin", "Crocodile", "Snake").
Wird nun ein "Lion" erzeugt, so wird für die nächsten beiden Erzeugungen kein "Lion" mehr erzeugt.
Lasst nun erneut 200 "Animals" einziehen - vielleicht in einen zweiten "Parkabschnitt" (Array)? :)
Muss sich der Pinguin noch immer Sorgen machen?
Viel Spaß!
heute erzeugen wir einen Zoo!
Erzeugt hierfür eine Basisklasse (oder Interface) "Animal" und einige Klassen die davon erben (z.B. "Lion", "Penguin", "Crocodile", "Snake").
Als nächsten Schritt wollen wir nun eine Factory-Klasse erzeugen, die sich am "Factory-Method-Pattern" orientiert.
In dieser Klasse soll eine Methode "createAnimal" existieren, die ein "Animal" zurückgibt.
Welches "Animal" zurückgegeben wird überlassen wir vorerst dem reinen Zufall ;)
Daher kann diese Klasse auch "RandomAnimalFactory" genannt werden.
Lasst nun 200 "Animals" in den Zoo einziehen.
Wie ist die Verteilung der "Animals" einer jeden Spezies in unserem Zoo?
Es kann mit der zufälligen Erzeugung zu einem gewissen Ungleichgewicht kommen.
So fühlt sich ein einzelner Pinguin gegen 199 Löwen sicher etwas in der Unterzahl ...
Erstellt nun eine zweite Factory-Klasse "BalancedAnimalFactory".
Diese soll ebenfalls die Methode "createAnimal" enthalten.
(Macht es nun evtl. Sinn sich auch bei den Factory-Klassen über ein Interface gedanken zu machen?)
Diese Factory soll nicht mehr komplett zufällig Tiere erzeugen sondern etwas ausgeglichener.
Die dort vorhandene "createAnimal" Methode soll wie folgt funktionieren:
Angenommen wir haben vier Tier-Klassen ("Lion", "Penguin", "Crocodile", "Snake").
Wird nun ein "Lion" erzeugt, so wird für die nächsten beiden Erzeugungen kein "Lion" mehr erzeugt.
Lasst nun erneut 200 "Animals" einziehen - vielleicht in einen zweiten "Parkabschnitt" (Array)? :)
Muss sich der Pinguin noch immer Sorgen machen?
Viel Spaß!
#1

von Pascal (130 Punkte)
- 26.09.2020 um 14:59 Uhr
Hallo Exception
Folgenden Probleme taten sich auf:
In der Factory werden verschiedene Objekttypen erstellt.
Dies habe ich nun so gelöst, dass die verschiedenen Objekttypen (Klassen) in der Factory hinterlegt werden.
Aus diesen Klassen werden dann die entsprechenden Objekte erzeugt.
Die Typesafety leidet etwas unter dieser Lösung.
Eine andere Lösung wäre gewesen, die Tiere zu klonen. Für die Aufgabe hätte es genügt, aber es gefiel mir nicht.
Den Zoo habe ich jetzt so gestaltet, dass er nicht weiss, welche Tiere er von der Factory bekommt.
Somit lässt sich die Factory einfach erweitern ohne dass der Zoo verändert werden muss.
Dafür muss der Zoo nach erhalt der Ware den Bestand umständlich ermitteln.
Für die Balanced Lösung habe ich die bestehende Factory mit einer zusätzlichen Funktion erweitert.
Würde man eine extra Factory erzeugen, dann müsste man später zwei Factories pflegen.
Alternativer Lösungsvorschlag:
Ein AnimalEnum
Dictionary erstellen mit AnimalEnum und AnimalKlasse
Anhand des Enum wird in der Factory das Animal erzeugt
Die Randomfunktion oder Balancedfunktion würde ich im Zoo erstellen.
Somit hätte die Factory die Aufgabe die Tiere zu erzeugen und der Zoo die Aufgabe die Tiere zu bestellen.
Zum Ergebnis:
Ob Random oder Balanced verwendet wird, hat wenig Einfluss auf das Ergebnis.
Bei Random ist die Verteilung meist ausgeglichen.
Bei Balanced wird die Verteilung auch nicht garantiert, da lediglich die letzten zwei Tiere nicht zur Auswahl stehen.
Beispielergebnis:
C#-Code
Schöne Grüsse und besten Dank für die Beschäftigung
Folgenden Probleme taten sich auf:
In der Factory werden verschiedene Objekttypen erstellt.
Dies habe ich nun so gelöst, dass die verschiedenen Objekttypen (Klassen) in der Factory hinterlegt werden.
Aus diesen Klassen werden dann die entsprechenden Objekte erzeugt.
Die Typesafety leidet etwas unter dieser Lösung.
Eine andere Lösung wäre gewesen, die Tiere zu klonen. Für die Aufgabe hätte es genügt, aber es gefiel mir nicht.
Den Zoo habe ich jetzt so gestaltet, dass er nicht weiss, welche Tiere er von der Factory bekommt.
Somit lässt sich die Factory einfach erweitern ohne dass der Zoo verändert werden muss.
Dafür muss der Zoo nach erhalt der Ware den Bestand umständlich ermitteln.
Für die Balanced Lösung habe ich die bestehende Factory mit einer zusätzlichen Funktion erweitert.
Würde man eine extra Factory erzeugen, dann müsste man später zwei Factories pflegen.
Alternativer Lösungsvorschlag:
Ein AnimalEnum
Dictionary erstellen mit AnimalEnum und AnimalKlasse
Anhand des Enum wird in der Factory das Animal erzeugt
Die Randomfunktion oder Balancedfunktion würde ich im Zoo erstellen.
Somit hätte die Factory die Aufgabe die Tiere zu erzeugen und der Zoo die Aufgabe die Tiere zu bestellen.
Zum Ergebnis:
Ob Random oder Balanced verwendet wird, hat wenig Einfluss auf das Ergebnis.
Bei Random ist die Verteilung meist ausgeglichen.
Bei Balanced wird die Verteilung auch nicht garantiert, da lediglich die letzten zwei Tiere nicht zur Auswahl stehen.
Beispielergebnis:
Random Animal Factory
57 - Penguin
55 - Crocodile
44 - Snake
44 - Lion
Balanced Animal Factory
49 - Crocodile
52 - Snake
50 - Lion
49 - Penguin

using System; using System.Collections.Generic; using System.Linq; namespace Zoo { public class Zoo { private static AnimalFactory animalFactory; public static List<IAnimal> AnimalsInZoo = new List<IAnimal>(); private static void Main() { animalFactory = new AnimalFactory(); AddRandomAnimals(200); Console.WriteLine("Random Animal Factory"); PrintZoo(); AddBalancedAnimals(200); Console.WriteLine("Balanced Animal Factory"); PrintZoo(); } private static void AddRandomAnimals(int numberOfAnimals) { AnimalsInZoo.Clear(); for (var i = 0; i < numberOfAnimals; i++) { AnimalsInZoo.Add(animalFactory.CreateRandomAnimal()); } } private static void AddBalancedAnimals(int numberOfAnimals) { AnimalsInZoo.Clear(); for (var i = 0; i < numberOfAnimals; i++) { AnimalsInZoo.Add(animalFactory.CreateBalancedAnimal()); } } private static void PrintZoo() { var animalTypeList = AnimalsInZoo.Select(x => x.GetType()).Distinct(); foreach (var animalType in animalTypeList) { var sum = AnimalsInZoo.Count(animal => animal.GetType() == animalType); Console.WriteLine(sum + " - " + animalType.Name); } } } public class AnimalFactory { private readonly List<Type> animalTypes; private Type lastAnimal; private Type secondLastAnimal; public AnimalFactory() { var availableAnimalTypes = new List<IAnimal> { new Crocodile(), new Lion(), new Penguin(), new Snake() }; animalTypes = availableAnimalTypes.Select(animalType => animalType.GetType()).ToList(); } public IAnimal CreateRandomAnimal() { var random = new Random(); var index = random.Next(animalTypes.Count); var animalClass = animalTypes[index]; return (IAnimal) Activator.CreateInstance(animalClass); } public IAnimal CreateBalancedAnimal() { var random = new Random(); var animalListReduced = new List<Type>(animalTypes); animalListReduced.Remove(lastAnimal); animalListReduced.Remove(secondLastAnimal); var index = random.Next(animalListReduced.Count); var animalClass = animalListReduced[index]; secondLastAnimal = lastAnimal; lastAnimal = animalClass; return (IAnimal)Activator.CreateInstance(animalClass); } } public interface IAnimal {} public class Lion : IAnimal {} public class Penguin : IAnimal {} public class Snake : IAnimal {} public class Crocodile : IAnimal {} }
Schöne Grüsse und besten Dank für die Beschäftigung
Kommentare:
Für diese Lösung gibt es noch keinen Kommentar
Seite 1 von 0
1