ObjectFactory

montify
Beiträge: 94
Registriert: 21.10.2012 22:43

ObjectFactory

Beitragvon montify » 02.10.2015 16:03

Hallo,
Ich sehe mir gerade ein Projekt an (XNA) um daraus zu lernen.

Jetzt gibts da ne Klasse ( _mainPresenter), die aber nirgends erstellt wird.

In der Game Klasse wird die Variable erzeugt:

Code: Alles auswählen

MainPresenter _mainPresenter;


dann in der Game.Initialize()


Code: Alles auswählen

 protected override void Initialize()
        {
            Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;

            _mainPresenter = ObjectFactory.GetInstance<MainPresenter>();
            _mainPresenter.Show();

            base.Initialize();
        }



Was macht die ObjectFactory klasse, scheint ja ne .Net klasse zu sein?
Wird sie vlt. mit GetInstance<> erstellt? Wenn ja warum?

auf MSDN steht auch nichts gscheites darüber.. :/
lg. alex

Benutzeravatar
NeoArmageddon
Beiträge: 1165
Registriert: 13.02.2012 20:34
Wohnort: Göttingen
Kontaktdaten:

Re: ObjectFactory

Beitragvon NeoArmageddon » 04.10.2015 13:58

Das was du dort siehst, ist das sogenannte "Factory Design Pattern". Du initialisiert sich eine Klasse nicht selbst, sondern es gibt eine andere Klasse, welche diese Aufgabe übernimmt. Dadurch kann u.a. sichergestellt werden, dass div. Abhängigkeiten erzeugt werden und konfiguration der Klassen zentral geregelt werden.

Wenn man es ganz einfach betrachtet, ist der "new" Befehl in C/C++/C# auch eine Factory, aber eine sehr einfache, die nur Speicherplatz belegt und den Konstruktor aufruft. Wenn man jedoch mehr beim erzeugen einer Klasse tun möchte, dann schreibt man dazu eine Factory. Schau am besten mal hier: https://de.wikipedia.org/wiki/Fabrikmethode

Benutzeravatar
Razer
Beiträge: 834
Registriert: 24.02.2012 20:08
Wohnort: Bayern
Kontaktdaten:

Re: ObjectFactory

Beitragvon Razer » 04.10.2015 14:02

Es wäre sehr hilfreich, wenn du das Projekt zur Verfügung stellen könntest (oder einen Link dazu, scheint ja öffentlich zu sein).
Ohne Sourcecode kann dir das auch kaum wer erklären.

Meine Vermutung jedoch: ObjectFactory ist, wie der Name bereits sagt, eine Factory-Klasse. Da steckt nicht viel Magie dahinter, es ist lediglich eine statische Klasse mit einer statischen Methode GetInstance<T>(). In dem Fall übergibst du dieser Methode einen Typen, hier MainPresenter und diese Factory-Methode erstellt dir davon eine Instanz (wsl. mit Voreinstellungen).

Du findest höchstwarscheinlich folgenden Code in der GetInstance<T>()-Methode:

Code: Alles auswählen

return (T)Activator.CreateInstance(typeof(T), null);

Also es wird lediglich dynamisch eine Instanz erzeugt (CreateInstance ruft wiederrum den parameterlosen Standard-Konstruktor auf).

Mehr dazu hier.

montify
Beiträge: 94
Registriert: 21.10.2012 22:43

Re: ObjectFactory

Beitragvon montify » 05.10.2015 09:35

Hallo,

Danke für eure unterstützung, tatsächlich kommt in den Projekt das FactoryPattern vor.
Aber bei den Beispiel oben hab ich herausgefunden das es sich um eine "Structure Map" handelt http://docs.structuremap.net/


Hat jemand erfahrung mit dem? Werde nicht schlau was das genau macht.

Irgendwie muss da was Registriert werden,...

Benutzeravatar
Razer
Beiträge: 834
Registriert: 24.02.2012 20:08
Wohnort: Bayern
Kontaktdaten:

Re: ObjectFactory

Beitragvon Razer » 05.10.2015 14:45

Structure Map ist, wie die Beschreibung auf der Seite perfekt angibt, ein Dependency-Injection Framework für .Net.
Eines von vielen um genauer zu sein.

Im Endeffekt ist das Ziel von DI, Abhängigkeiten zu eliminieren. Als Beispiel:

Ein Projekt MainGame und ein Projekt MainGame.Rendering. Ersteres ist das Spiel selbst und enthält lediglich den Code
zum Rendern spielrelevanter Ressourcen. MainGame.Rendering enthält hingegen den Rendering-Code, sprich GraphicsDevice, Shading, SpriteBatch, usw.

Normalerweise würdest du nun MainGame.Rendering referenzieren und das ganze ist getan. Interessant wird es aber, wenn du folgende
Sub-Typen hast:
- MainGame.Rendering.DirectX9
- MainGame.Rendering.DirectX10
- MainGame.Rendering.OpenGL

Beim DI-Pattern werden hauptsächlich Schnittstellen (Interfaces) genutzt. Letzten Endes lädt das DI-Framework die nötigen DLLs und injiziert die Referenzen On-Demand zur Laufzeit. Zur Compiletime besteht keinerlei Referenz zu einer dieser genauen Implementierungen. Lediglich eine gemeinsame Referenz (von MainGame und MainGame.Rendering.X) zu einem Interface das besagte Dinge definiert (ISpriteBatch oder so z.B.).

Im Code würdest du nun vmtl. in etwa sowas aufrufen:

Code: Alles auswählen

ISpriteBatch batch = StructureMap.Get<ISpriteBatch>();


Je nachdem, welches Rendering-Interface (DX9, 10, 11, 12, OpenGL) du nun gewählt hast, erhälst du den jeweiligen korrekten SpriteBatch. Jedoch in Form eines Interfaces, welches die gemeinsame Basis Aller darstellt.

Auch hilfreich um zwischen Test- und Deployment-Environments zu wechseln. Sprich, du hast eine Implementierung die Werte simuliert, während eine andere tatsächlich was damit anfängt und echte Werte nutzt.

Hoffe, ich konnte dir das Ganze etwas verdeutlichen.

montify
Beiträge: 94
Registriert: 21.10.2012 22:43

Re: ObjectFactory

Beitragvon montify » 06.10.2015 09:32

Wow danke für die Erklärung, aber glaube sowas ist für mein Projekt zu viel :)

Irgendwie beneide ich euch alle, ihr seit ja in allen C# Angelegenheiten gut drauf!

Benutzeravatar
Razer
Beiträge: 834
Registriert: 24.02.2012 20:08
Wohnort: Bayern
Kontaktdaten:

Re: ObjectFactory

Beitragvon Razer » 06.10.2015 14:23

montify hat geschrieben:Wow danke für die Erklärung, aber glaube sowas ist für mein Projekt zu viel :)

Irgendwie beneide ich euch alle, ihr seit ja in allen C# Angelegenheiten gut drauf!


Für Spieleprojekte ist das meist zu overpowered. Bei Engines wird das durchaus öfters gemacht und ist dementsprechend nötig um die Engine auf allen Plattformen und Render-Frameworks zu unterstützen. Wobei man das dann auch mit C++ macht (zwecks Plattformunabhängigkeit).

Das ganze macht aber bei Programmen durchaus Sinn, gerade wenn's um Erweiterung (Stichwort Plugins, AddIns) geht. Ich nutze das in meinen Projekten ebenfalls, jedoch in eigener Implementierung und etwas abgeändert.

Zur Erfahrung: Die meisten hier sind ja auch schon etwas ältere Hasen und haben schon viele Jahre (teils professionelle) Programmiererfahrung. Auf die Dauer lernt man einiges ;) Drum: Immer schön am Ball bleiben und stets weiterbilden.

Benutzeravatar
NeoArmageddon
Beiträge: 1165
Registriert: 13.02.2012 20:34
Wohnort: Göttingen
Kontaktdaten:

Re: ObjectFactory

Beitragvon NeoArmageddon » 06.10.2015 15:23

Du brauchst Factories spätestens, wenn du deine Objekte nicht mehr in C/C# sondern extern beschreiben möchtest (Stichwort Datadriven Design).

Nehmen wir an, du hast eine Klasse "Creature" mit einem "Health" Wert und möchtest nun daraus Spielobjekte wie Spieler, Monster, NPCs etc machen, aber das ganze extern in z.B. XML definieren, anstatt eine ganze Menge an C# Klassen von Creatures erben zu lassen. Dann würdest du eine "CreatureFactory" bauen, mit einer Methode

Code: Alles auswählen

static Creature* getCreature(string type) {...};


In einer XML Datei hast du dann Einträge wie:

Code: Alles auswählen

<creatures>
   <creature name="Player" health="100" />
   <creature name="NPC" health="999999" />
   <creature name="Monster1" health="10" />
   <creature name="Monster2" health="50" />
   <creature name="MonsterBoss" health="500" />
</creatures>


Rufst du jetzt die Factory mit versch. Parametern auf:

Code: Alles auswählen

Creature* aPlayer = CreatureFactory::getCreature("Player");
Creature* aMonster = CreatureFactory::getCreature("Monster2");
Creature* aBoss = CreatureFactory::getCreature("MonsterBoss");


kümmert sich die Factory darum, in der XML Datei nach dem gewünschten Typ zu suchen, ein "Creature"-Objekt zu erstellen, und die richtigen Werte (hier der Health-Wert) zu setzen.

So hat man das eigentliche vererben von Klasseneigenschaften aus dem Programmcode in externe Dateien verlagert, die von Designern (oder dem Programmierer) einfacher bearbeitet werden können. Im Programm hast du zusätzlich den Vorteil, dass du für "Kreaturen" nur eine Klasse hast, was deine Spielweltsimulation drastisch vereinfacht. Und dennoch können hier verschiedene Creature-Instanzen ganz verschiedene Eigenschaften haben. Achja, und so wird das Spiel viel Modding freundlicher ;)

Nu zum Vergleich, mit "klassischem" OOP Ansatz würde das oben so aussehen und man müsste bei jeder Änderung alles neu kompilieren:

Code: Alles auswählen

class Creature {
   public:
   int health;
};
class Player : Creature {
   Player() {health = 100;};
};
class NPC : Creature {
   Player() {health = 999;};
};
class Monster1 : Creature {
   Player() {health = 10;};
};
class MonsterBoss : Creature {
   Player() {health = 500;};
};

Benutzeravatar
Razer
Beiträge: 834
Registriert: 24.02.2012 20:08
Wohnort: Bayern
Kontaktdaten:

Re: ObjectFactory

Beitragvon Razer » 06.10.2015 17:53

Gute Ergänzung, an das hatte ich im Moment gar nicht gedacht. Definitiv ein gutes Beispiel für Factories.
Sollte man generell so machen, wenn man viele Objekte vom gleichen Typ hat, aber unterschiedliche Eigenschaften zuweist.
Durch eine ID oder ähnliches kann man jede Instanz von Creature auch identifizieren, um was es sich denn genau handelt.

Ein Beispiel aus der Anwendungs-Ecke (und damit meinem momentanen Milieu):
Presets in Editoren. Man kann per XML ganz einfach vordefinierte Blöcke serialisieren und deserialisieren. Das ermöglicht, dass man
z.B. ein Objekt "Player" generieren kann, welches automatisch bereits eine Sprite-Component (bei Komponenten-basierten Engines), eine Sound-Component, KeyboardInteraction-Component, usw. enthält und diese vorkonfiguriert (Leben, Sprite-Grafik, ...).

Oder anderer Anwendungsfall wäre Erweiterbarkeit. Bei TKMap zum Beispiel werden AddIns rein in XML definiert. Die Logik wird in Code ausgelagert. Ähnliches System wie XAML/WPF. Das macht das ganze extrem flexibel, kann von nicht-Programmierern designed werden und kann viel leichter um einen Designer erweitert werden, als wenn das ganze fix in Code passiert.

montify
Beiträge: 94
Registriert: 21.10.2012 22:43

Re: ObjectFactory

Beitragvon montify » 06.10.2015 18:09

Danke für die Beispiele! Aber das ist für mein Projekt (Proceduraler Planet) glaub ich nicht nötig bzw. zu "overloaded"?!:)


Zurück zu „C#“

Wer ist online?

Mitglieder in diesem Forum: ahrefs (Bot) und 1 Gast