| 

.NET C# Java Javascript Exception

5
Hallo Zusammen,

ich versuche gerade etwas zu programmieren und komme nicht weiter.

Ziel ist es, bis zu N-Klassen zu haben, die alle von einem Interface erben.

Die Funktionen der verschiedenen Klassen sollen aller über eine Verwaltung aufrufbar sein, hier habe ich mich für ein Singleton-Muster entschieden.

Mein Interface sieht so in etwa aus:
public interface IMonster
{
public bool isAngry();
public string Name();
}


Eine Instanzen sehen dann so aus:
public class EvilBoss
{
public bool isAngry()
{
return true;
}
public string Name()
}
return "Very Evil Boss";
}
}
public class SweetLittleBunny
{
public bool isAngry()
{
return false;
}
public string Name()
}
return "Cute little Bunny";
}
}


Ich glaub jetzt ist soweit klar, was ich vor hab.

Jetzt kommt mein Problem, ich möchte sowas machen wie:
NpcManagement<EvilMonster>.Instanz.getName();
NpcManagement<SweetLittleBunny>.Instanz.getName();


Mein Singleton sieht im Moment so aus, was aber irgendwie auch nicht richtig ist...
private static volatile NpcManagement<IMonster> _instanz;
private static readonly object lockBlock = new Object();

private NpcManagement(){}

public static NpcManagement<IMonster> Instanz
{
get
{
if (_instanz == null)
{
lock (lockBlock)
{
if (_instanz == null)
{
_instanz = new NpcManagement<IMonster>();
}
}
}
return _instanz;

//Jetzt würden hier dann die einzelnen Funktionen und Attribute des IMonster Interface aufrufbar sein müssen.
}
}


Ich hoffe mit diesem bisschen Code ist irgendwie klar, was ich vor habe. Ich möchte nicht in jeder Klasse, die von IMonster erbt ein Singleton haben :)

Vielleicht bin ich auch gerade auf dem Holzweg.

Kann mir jemand helfen? Oder gibt es sogar eine bessere Möglichkeit?

Viele Grüße
Bibo

PS: Ich fange gerade an, sauber zu Programmieren. In meinen Augen ist das relativ Sauber, was ich vor habe. Ich bin für jeden Tipp dankbar, der mir hilft :)
News:
03.07.2014
Bibo1987 256 1 8
Könntest du bitte noch sagen was genau nicht funktioniert bzw. worüber sich der Compiler beschwert? Ich hab da so einen Verdacht, aber da dein Code stark nach C# aussieht frage ich lieber erst nochmal nach.
phg 04.07.2014
3 Antworten
1
Hallo Boibo

Zuerst muss dein Interface Typisiert sein.

public interface IMonster<T>
{
bool isAngry();
string Name();
T Instance { get; }
}


Der Abruf der Werte erfolgt dann über die Instance des Interaces

public static class NPCManagement
{
private static readonly Dictionary<string, object> _managementDictionary = new Dictionary<string, object>();

// Die Instanz in den _managementDictionary laden
public static void Register(string key, object instance)
{
if(!_managementDictionary.ContainsKey(key)) _managementDictionary.Add(key, instance);
}

public static T GetInstance<T>(string key)
{

return ((IMonster<T>)_managementDictionary[key]).Instance;

}
}


In der Klasse kannst du dich beim NPCManagement direkt anmelden.
Die Klasse EvilBoss sieht dann so aus.

public class EvilBoss :  IMonster<EvilBoss>
{
public EvilBoss() { NPCManagement.Register("EvilBoss", this); }

public bool isAngry()
{
return true;
}

public string Name()
{
return "Very Evil Boss";
}

public EvilBoss Instance
{
get { return this; }
}
}


Beachte das jetzt das Interface vom Typ EvilBoss ist, und somit im NPCManagement über GetInstance abgerufen werden kann.
Der Abruf sieht folgedermassen aus:

MessageBox.Show(NPCManagement.GetInstance<EvilBoss>("EvilBoss").Instance.Name());


Gruss Alex
04.07.2014
Maendler 214 7
Vielen Dank für die Antwort, genau das hab ich gebraucht.
Bibo1987 04.07.2014
3
PS: Ich fange gerade an, sauber zu Programmieren. In meinen Augen ist das relativ Sauber, was ich vor habe. Ich bin für jeden Tipp dankbar, der mir hilft :)

Kurzfassung meines Tipps: Vergiss das Singleton-Muster, so wie Du es kennst.

Etwas ausführlicher:
Das Singleton wird heute gerne dazu verwendet, einen zentralen Zugriffspunkt zu irgendetwas zu haben. Das entspricht in etwa einer globalen Variable, auf die von überall zugegriffen werden kann. Und genau das ist das Problem. Ich sehe einer Klasse nicht durch Betrachten Ihrer öffentlichen Schnittstelle an, dass Sie eine Abhängigkeit zu dieser globalen Instanz hat. Jede Abhängigkeit, die eine Klasse eingeht, sollte ihr im Konstruktor übergeben werden. Damit bin ich gleichzeitig auch den globalen Zugriffspunkt los, ich sage der Klasse, welche Abhängigkeit sie benutzen soll, und lasse sie das nicht selbst kontrollieren (Inversion of Control). Diese Entscheidung möchte ich nämlich unter gewissen Umständen anders treffen können, als Beispiel sei hier nur der Test genannt.
Für mich ist eine Singleton-Implementierung als globaler Zugriffspunkt ein Anti-Pattern. Es gibt verschiedene Refaktorisierungen, um auch in großen Legacy Codebases sukzessive alle Singletons zu töten. Eine zumeist unabdingbare Voraussetzung, um in eine solche Codebase automatisierte Tests einzuziehen und die Komplexität des Gesamtsystems durch explizite Modellierung von Abhängigkeiten zu reduzieren.
Das Singleton sollte meiner Meinung nach lediglich als ein Lebenszyklus verstanden werden. Wie lange existiert ein Objekt? Es kann über die gesamte Programmlaufzeit hinweg dasselbe Objekt existieren, und alle die es verwenden, verwenden damit wieder eine globale Instanz. Diesmal allerdings, ohne es zu wissen und sich explizit an diese Entscheidung gebunden zu haben.
05.07.2014
ffordermaier 8,4k 3 9
1
Wenn ich mir Deinen Code so ansehe, muss ich an das Factory-Pattern denken. Dein Singleton stellt die Factory dar und soll Instanzen unterschiedlicher Klassen, die über ein gemeinsames Interface verfügen, zurückgeben.
Es müsste dazu in Instanz einen Konstruktor geben, der einen Parameter erhält welche Klasse zu erstellen ist.
Bisher hast nur ein leeres Singleton vom Typ NpxManagement erstellt mit dem Interface IMonster erstellt. Wenn Du keine Factory in dieser Art erstellen möchtest, dann hier mein nächster Vorschlag:

Statt mit NpcManagement<IMonster> wäre es besser mit einer Templateklasse zu arbeiten:
NpcManagement<T> und Instanzen vom Typ <T> zu erstellen. Man könnte T zusätzlich auf das Interface einschränken: NpcManagement<T> where T : IMonster (noch vollständig qualifizieren!)

Vielleicht hilft das erst einmal weiter.
04.07.2014
edvservice 1,4k 1 6

Stelle deine Interface-Frage jetzt!