Frage

Ich bin mit dem Ziel eine Reihe von Objekten zu erstellen, von denen jeder eine eindeutige Kennung hat. Wenn ein Objekt bereits mit dieser Kennung vorhanden ist, mag ich das vorhandene Objekt verwenden. Ansonsten möchte ich einen neuen erstellen. Ich versuche nicht, das Wort Singleton zu verwenden, weil ich es ist ein schmutziges Wort, das hier wissen ...

Ich kann eine Factory-Methode verwenden:

    // A map of existing nodes, for getInstance.
private static Map<String, MyClass> directory = new HashMap<String, MyClass>();

public static MyClass getInstance(String name) {
    MyClass node = directory.get(name);
    if(node == null) {
       node == new MyClass(name);
    }
    return node;
}

oder gleich, ich könnte eine separate MyClassFactory Methode haben.

Aber ich hatte die Absicht, MyClass Unterklasse:

public class MySubClass extends MyClass;

Wenn ich nicht mehr tun, und rufen Sie MySubClass.getInstance ():

MyClass subclassObj = MySubClass.getInstance("new name");

... dann subclassObj wird eine einfache MyClass, kein MySubClass sein.

Doch übergeordnete getInstance () in jeder Unterklasse scheint hacky.

Gibt es eine saubere Lösung fehle ich?


Das ist die verallgemeinerte Version der Frage. Weitere Einzelheiten, da die Beantworter für sie gefragt.

Das Programm ist für einen gerichteten Graphen von Abhängigkeiten zwischen den Knoten Erzeugen Teile der Software repräsentiert. Subklassen sind Java-Programme, Web Services, Gespeicherte SQL-Prozeduren, Message-Driven Trigger, etc.

So wird jede Klasse „ist-a“ Element in diesem Netzwerk und verfügt über Methoden Abhängigkeitsbeziehungen mit anderen Knoten zu navigieren und zu ändern. Der Unterschied zwischen den Unterklassen wird die Umsetzung der populate() Methode verwendet, um das Objekt von der entsprechenden Quelle einzurichten.

Lassen Sie uns sagen, dass der Knoten mit dem Namen ‚login.java‘ erfährt, dass es eine Abhängigkeit von ‚checkpasswd.sqlpl‘ hat:

this.addDependency( NodeFactory.getInstance("checkpasswd.sqlpl"));

Das Problem ist, dass das checkpasswd.sqlpl Objekt kann oder nicht zu diesem Zeitpunkt bereits vorhanden ist.

War es hilfreich?

Lösung

Die statische Methode beruht auf der übergeordneten Klasse definiert, und es ist statisch als auch genannt. Also, es gibt keine Möglichkeit, in der Methode, zu wissen, dass Sie es auf der Unterklasse genannt habe. Der Java-Compiler wahrscheinlich löst auch den Anruf statisch zu einem Aufruf der übergeordneten Klasse.

So werden Sie brauchen entweder die statische Methode in Ihrem Kind Klassen neu implementieren, wie Sie vorschlagen, oder sie ist nicht statisch, so dass Sie (auf einer Hierarchie von Fabrik Objekte , nicht Klassen) Vererbung, oder übergeben Sie einen Parameter, um den Typ, um anzuzeigen, die Sie erstellen möchten.

Überprüfen Sie die EnumSet.noneOf () -Methode aus. Es hat ein ähnliches Problem wie Sie, und es löst es durch die java.lang.Class Methode übergeben. Sie könnten newInstance auf die Klasse. Aber persönlich, ich würde nur Factory-Objekte verwendet, anstatt Klassen mit statischen Methoden.

Andere Tipps

Haben Sie sich in Guice? Nicht sicher, ob es das Problem genau lösen würde, aber es wirkt als generisches Werk und Dependency Injection Container und beseitigt nicht typsicher String Schlüssel.

, nachdem Sie Erklärung des Problems zu lesen Ich denke, Ihr macht es für sich selbst sehr schwierig durch den Unter in Ihrem Diagramm Aufbau Klassierung. Ich denke, das Problem viel einfacher wird, wenn Sie die Abhängigkeitsgraphen aus der „Programminformation“

trennen

Sie eine Schnittstelle verwenden, wie zum Beispiel:

Public Interface Node<T> {
  public Object<T>    getObject();
  public String       getKey();
  public List<String> getDependencies();
  public void         addDependence(String dep);
}

und dann eine Fabrik verwenden, um Sie Knoten zu instanziiert

Sie scheinen, dass irgendwo zu implizieren, Sie wissen, welche Klasse sollte es sein, wenn sie nicht existiert. Wenn Sie diese Logik in Ihrer Fabrik implementieren sollten Sie die richtigen Klassen erhalten.

Auf diese Weise kann auch keine Notwendigkeit, tatsächlich aus der Fabrik zurückgekehrt war zu wissen, welche Klasse haben sollte.

Ich würde auch wahrscheinlich make ‚MyClass‘ eine Schnittstelle, wenn Sie ein Factory-Muster erwägen.

Die Klasse Klasse ist mit der Art der Instanz parametriert es schaffen kann. (Z. B.: Klasse ist eine Fabrik für String-Instanzen)

Ich sehe keinen Weg, um die Art von Instanz zu erhalten um zu wissen, die erstellt werden sollen, wenn Sie getOrCreate hier die Factory-Methode verwenden, so würde ich empfehlen, es an die Methode übergeben und Parametrisierung von der Art erzeugt werden:

private static Map<String, MyClass> directory = new HashMap<String, MyClass>();

public static <T extends MyClass> T getInstance(String name, Class<T> generatorClass)
{
  MyClass node = directory.get(name);    
  if(node == null) {
    node = generatorClass.getConstructor(String.class).newInstance(name);
    directory.put(name, node);
  }
  return node;
}

Auch ich bemerkte, dass Sie die neu konstruierten Knoten im Verzeichnis nicht tatsächlich setzten - ich gehe davon aus, das ist ein Versehen. Sie können auch diese Methode mit einem anderen überlasten, die nicht mit einem Generator und hartcodiert auf den Standardtyp nehmen haben:

public static MyClass getInstance(String name) {
  return getInstance(name, MyClass.class);
}

Sie wollen wahrscheinlich Dependency Injection. Es wäre verallgemeinern, was Sie versuchen etwas zu tun.

Auch Vererbung ist wahrscheinlich nicht genau das, was Sie entweder benötigen. Nie verwenden, wenn Sie das passieren kann „ist-ein“ Test. Wenn Ihre geerbte Klasse „Hat-einen“ eindeutigen String-Tag (im Wesentlichen das ist, was Ihre Klasse zu sein scheint) bedeutet es nicht, es „ist-a“ ...

Sie könnte man jedoch auf den anderen halten. Es gibt wahrscheinlich ziemlich viele Lösungen, aber A) Sie nicht Ihre gesamte Liste der Anforderungen veröffentlichen, so können wir, aber erraten, und B), was Sie wahrscheinlich wollen Dependency Injection. :)

Das Muster erscheint eine Art Flyweight zu sein (strukturell , wenn nicht eine perfekte Ergänzung für Vorsatz.)

Die populate Methode, wie beschrieben, könnte auf die Template Muster abgebildet werden, obwohl sie nicht notwendigerweise die geäußerten Bedenken begegnen.

Was würde ich vorschlagen, ist eine Verallgemeinerung der Fabrik, mit einem create (statt getInstance, die einen Singleton bedeuten, für mich jedenfalls) Methode für die verschiedenen Typen, die Sie erwarten.

public static MyClass createJavaNode(String name, <differentiator>);
public static MyClass createSqlPlNode (String name, <differentiator>);
.
.
.

Das Wissen darüber, wie eine name Karten zu einem <differentiator> ist wirklich eine Implementierung Wahl. Idealerweise würde es eine polymorphe create sein und die Differenzierung von node Art sein würde. Die create Methode gibt MyClass, ist aber wirklich die Unterklassen zurück. Ich würde betrachten stark MyClass entweder eine Schnittstelle oder eine abstrakte Klasse, mit einem abstract populate Verfahren machen (es gibt die Template).

Aus der Beschreibung scheint es wirklich, dass es die Schaffung Verhalten, das zwischen den Typen, nicht das Verhalten der Unterklassen selbst, so der Fall für das Refactoring von MyClass auf eine Schnittstelle oder eine abstrakte Klasse wird stärker unterscheidet.

R. A. Heinlein paraphrasieren, TANSTAAFL - TANSTAAFL - irgendwo das Wissen, wie die verschiedenen Arten zu schaffen, hat in der Anwendung existieren. So Ihre Wahl ist, dass das Wissen in der Factory-Klasse zu setzen, wie einige der anderen Antworten zum Ausdruck gebracht haben, oder die Entscheidung von zu trennen, was Implementierung von erstellt wird wie es ist erstellt. Es scheint, als ob es eine Möglichkeit zum Scannen eines Dateisystems ist und das Sammeln der Nodes von ihm. Dieser Code wird (oder kann) kennen die type der Node (die Antwort auf die was ), die erstellt werden soll.

Ob das als switch oder in einer OO Art und Weise umgesetzt wird (eine der Zeiten, in denen tabellengesteuerten Versand wäre schön) ist bei Ihnen. Ist dies etwas, die nützlich sein könnten, kann ich erweitern auf das hier.

BTW, wenn das Kernverhalten von MyClass für einige Unterklassen werden erweitert oder modifiziert muss, ist, dass, wenn ein Decorator nützlich sein könnten.


Original Antwort:

Sie können die Decorator oder Vorlage Design Patterns als Alternativen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top