Frage

In einem Projekt, das ich seit vielen Jahren beteiligt, habe ich entwickelt sich allmählich ein Entwurfsmuster, die für mich als äußerst nützlich erwiesen hat. Ich fühle mich manchmal soll ich damit ein bisschen evangelisch, aber ich würde ein bisschen peinlich, wenn ich versuche, und fand heraus, dass es nur meine Version von jemandes alten Hut war. Ich habe gegraben durch Design Patterns suchen sie vergeblich, und ich habe nicht über jemand anderes darüber zu sprechen laufen, aber meine Suche hat keinen Anspruch auf Vollständigkeit gewesen.

Die Kernidee ist mit einem Broker-Objekt, das eine Reihe von Definitionsobjekten verwaltet, wobei jede Objektdefinition einen möglichen Wert einer komplexen Eigenschaft darstellt. Als Beispiel könnten Sie Auto, Flugzeug und Generator Klassen, die alle eine Engine haben. Auto nicht über eine eigenes Engine Objekt speichern, es speichert einen Referenzschlüssel von einer Art, die die Art von Motor heißt es, hat (wie eine ganze Zahl oder String-ID). Wenn wir auf Eigenschaften oder Verhalten eines Engine aussehen wollen, sagen WankelEngine, fragen wir Objekt das EngineTypeBroker Singleton-Objekt für WankelEngine Definition, die Schlüsselreferenz übergeben. Dieses Objekt kapselt, was interessant ist, über EngineTypes zu wissen, möglicherweise einfach eine Eigenschaftsliste zu sein, aber möglicherweise Verhalten auf mich auch geladen zu haben.

Also, was es erleichtert ist eine Art gemeinsamen, losen gekoppelten Aggregation, wo viele Autos eine WankelEngine haben können, aber es gibt nur ein WankelEngine Definitionsobjekt (und die EngineTypeBroker können das Objekt ersetzen, die lose Kopplung in verbesserter Laufzeit morphism nutzen ).

Einige Elemente dieses Musters, wie ich es verwenden (Fortsetzung Engine als Beispiel verwenden):

  1. Es gibt immer IsEngineType (x) und Engine (x) Funktionen zur Bestimmung, ob ein gegebener Wert ein gültiger Referenzschlüssel für eine Engine ist und zum Abrufen des Enginedefinitionsobjekts zu einem Referenzschlüssel entsprechen.
  2. I mehr Formen des Referenzschlüssels für einen bestimmten Engine, immer mindestens einen String Namen und die Definition Objekt selbst, häufiger immer erlaubt als nicht eine ganze Zahl ID, und manchmal Objekttypen, die eine Engine aggregieren. Dies hilft bei der Fehlersuche, macht den Code flexibler und, in meiner besonderen Situation, erleichtert eine Menge Abwärtskompatibilitätsprobleme in Bezug auf ältere Praktiken. (Die übliche Art und Weise verwendet, um Menschen dies zu tun, ist in diesem Zusammenhang des Projektes waren Hashes für jede Eigenschaft zu definieren, eine Engine hat und die Eigenschaften von Referenzschlüssel sehen könnte.)
  3. Üblicherweise ist jede Definition Beispiel eine Unterklasse einer allgemeinen Klasse für diese Definition Typ ist (das heißt WankelEngine erbt Engine). Klassendateien für Definitionsobjekte werden in einem Verzeichnis wie / Def / Engine gehalten (das heißt WankelEngine Klasse wäre / Def / Engine / WankelEngine). So ähnliche Definitionen werden zusammen gruppiert, und die Klassendateien ähneln Konfigurationsdateien für den Engine, aber mit der Möglichkeit, Code zu definieren (normalerweise nicht in Konfigurationsdateien gefunden).

Einig trivialen illustratives Beispiel Pseudo-Code:

class Car {

    attribute Name;
    attribute EngineTypeCode;

    object GetEngineTypeDef() {
        return EngineTypeBroker->EngineType(this->GetEngineTypeCode());
    }

    string GetDescription() {
        object def = this->GetEngineTypeDef();
        return "I am a car called " . this->GetName() . ", whose " .
            def->GetEngineTypeName() . " engine can run at " .
            def->GetEngineTypeMaxRPM() . " RPM!";
    }

}

So gibt es einen Namen gibt für das?

War es hilfreich?

Lösung

SingletonRegistry

Glauben Sie mir oder nicht. Ich war heute Morgen genau dasselbe denken.

Ich habe dieses Muster verwendet, vor, aber ich habe nie eine Referenz für die es noch wissen, wie es zu nennen.

Ich glaube, eine Art „Freigestellte“ Singleton ist, wo die Instanzen irgendwo gespeichert sind, und sie werden mit einem Schlüssel erhalten.

Das letzte Mal, dass ich es verwenden, war es, Daten aus verschiedenen Quellen abgerufen werden.

hatte ich etwa 50 Datenbank-Tabellen (es 10 machen) Und ich habe einen Front-End „Tisch“, wo die Daten angezeigt waren werden, aber die Daten aus diesen Quellen stammen könnten und jedes erfordert unterschiedliche Logik (Abfragen, Joins, Schlüssel, etc.)

Das vordere Ende „konfigurierbar“ war, so konnte ich nicht wissen, welche Werte angezeigt werden sollten, und andere, die nicht.

Die Lösung war die column zu nehmen (im Frontend) als Schlüssel, und erhält die richtige Instanz die richtige Abfrage zu erstellen.

Dies wurde in einer Hash-Karte am Anfang installiert und später aus einer Datenbanktabelle abgerufen.

Der Code war wie folgt:

class DataFetcher {
    abstract Object getData( Object id );
}

class CustomerNameDataFetcher extends DataFetcher {
    Object getData( Object customerId ) { 
        // select name from customer where id = ? 
     }
}

class CompanyAdressDataFetcher extends DataFetcher { 
     Object getData( Object customerId ) { // don't ask why.
          // select name from company , customer where customer.co = company.co and cu = ?  etc.
     }
} 

class ProductColor extends DataFetcher { 
     Object getData( Object x ) { 
     // join from customer to color, to company to season to a bunch of table where id = ? 
}

// And the list goes on.

Jede Unterklasse verwendet, um verschiedene Logik.

Zur Laufzeit der Benutzer konfiguriert ist es Ansicht und wählen, was er sehen möchte.

Wenn der Benutzer die Spalten ausgewählt, um zu sehen, habe ich die Spaltennamen und eine ID, die Daten zu holen.

Die DataFetchers alle in der übergeordneten Klasse installiert wurden (ich wollte keine separeate Klasse dafür haben) in einer Klassenmethode.

class DataFetcher {
    abstract Object getData( Object id );

    private static final Map fetchers = new HashMap();static { 
        fetchers.put("customer.name", new CustomerNameDataFetcher() );
        fetchers.put("company.address", new CompanyAdressDataFetcher () );
        fetchers.put("product.color", new ProductColor () );
        ...
    }
    public static DataFetcher getFetcher( String id ) { 
        return fetchers.get( id );
    }      

}

Am Ende des vorderen Ende Tisch füllen ich es einfach so nennen:

Pseudo-Code

 for each row in table 
      for each column in row
          column.text = DataFetcher.getFetcher( column.id ).getData( row.id )
       end
 end

Ist es so? Oder muß ich falsch gelesen Ihre Beschreibung und ich ist ganz anders aus.

Schließlich denke ich, das SingletonRegistry oder so ähnlich genannt wird. I (wahrscheinlich) wie Sie, erstellt diese aus der Not. Die Chancen sind dies ein weit verbreitetes Muster ist.

Andere Tipps

Ich habe ein ähnliches Muster wie dies zuvor verwendet, am häufigsten in den Spielen. Ich würde eine WeaponDefinition und WeaponInstance Klassen (nicht ganz mit diesen Namen). Die WeaponDefinition Klasse (und verschiedene Unterklassen, wenn ich verschiedene Arten von Waffen hat, zB Nahkampf vs Projektil) würden für die Verfolgung der globalen Daten für diese Art von Waffe (Feuerrate, max Munition, Name, usw.) verantwortlich und hat die gesamte Logik. Die WeaponInstance Klasse (und Subklassen) enthalten den aktuellen Zustand in der Zündfolge (für die Verwendung mit der Feuerrate zu vergleichen), die aktuelle Munition Zahl und ein Zeiger (es könnte einige Schlüssel in eine Manager-Klasse sein wie in Ihrem Beispiel, aber das scheint keine Anforderung des Musters) an die WeaponDefinition zu sein. Die WeaponInstance hat eine Reihe von Funktionen zum Brennen, Nachladen, usw., die nur die entsprechende Methode auf dem WeaponDefinition Instanz aufrufen, sich als Argument übergeben. Das bedeutet, die WeaponDefinition Sachen für jeden Tank / Soldaten / Flugzeug in der Spielwelt nicht dupicated, aber sie alle haben ihre eigene Munition zählt, etc.

Ich habe keine Ahnung, was es heißt, und ich bin nicht sicher, es ist ganz das gleiche wie das, was du redest, aber ich denke, es ist in der Nähe. Es ist auf jeden Fall sinnvoll.

Klingt wie eine Kombination von GoF Builder, Prototype und vielleicht Featherweight mir.

Es klingt wie eine Vielzahl von einem Fliegengewicht (viele Autos teilen ein WankelEngine). Aber wie geht der Sinn? Die meisten Autos haben einen Motor, aber wie können die gleiche Instanz eines Motors viele von ihnen haben? Sie würden nicht weit auf diese Weise erhalten. Oder meinen Sie, dass viele Autos eine Maschine vom Typ WankelEngine haben? Spose, dass mehr Sinn macht. Was ist dann die Verwendung der „WankelEngine Definition Objekt“? Ist es eine Fabrik, die Aromen des Objekts und Leiten sie zurück an den Anforderer baut? Wenn ja es klingt nicht wie ein Definitionsobjekt, klingt eher wie eine Fabrik, die in den Parametern des Objekts unter zu bauen und gab dieses Objekt zurück.

ich hier ein paar gute GoF Praktiken sehen zu tun, und zwar, dass Sie statt erben komponieren (mein Auto hat Engine eine Maschine gegen mein Auto ist ein WankelEngine). Ich wünschte, ich könnte das Zitat genau erinnern, aber es ist so etwas wie „Erbe bricht Kapselung“ und „für Komposition der Vererbung“.

Ich bin gespannt, welches Problem dadurch gelöst wird. Ich glaube, Sie haben eine Menge Komplexität hinzugefügt und ich bin nicht die Notwendigkeit einer solchen Komplexität zu sehen. Vielleicht ist es etwas speziell auf Ihre Sprache, die ich nicht verstehe.

Die GoF Jungs diskutieren Sie komponieren Muster in größere Muster, MVC insbesondere ein Aggregat von drei anderen Mustern. Klingt wie man so etwas getan haben.

Es klingt ein bisschen wie Service Locator, in dem Ihre Leichtgewichte sind als Singletons registriert.

Was Sie haben, ist eine Karte, auch bekannt als Wörterbuch. Sie haben nur eine einzigartige Torsion auf sie, indem er mehrere Schlüssel zu einem Objekt zugeordnet werden.

Warum sein eine Karte:

  • hält einen Schlüssel
  • Mit der Taste einen Wert von einiger Datenstruktur abzufragen.

Hier finden Sie Implementierungen in:

  • STL (umfassen: map)
  • Java (Import: java.util.Dictionary)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top