2009-10-16 18 views
9

das Blatt in dem Verbund die Komponente implementiert, die das Add entfernen und GetChild Methoden, die er nie (Verletzung der Schnittstelle Segregation) verwenden wirdIst das zusammengesetzte Muster SOLID?

so ist die Verwendung von zusammengesetzten Muster SOLID?

Link zu Verbund http://www.dofactory.com/Patterns/PatternComposite.aspx

+0

Ihre Frage ist unklar. Auch, was meinst du mit "SOLID" – monksy

+0

Ich fügte eine SOLID-Verbindung für den Fragesteller, oben, hinzu. – SingleShot

+0

SRP und LSP werden auch zusammen mit ISP verletzt. SOLID ist also gefährlich. :) – Narek

Antwort

10

Der wirkliche Geruch im Muster wie in Ihren Link und die meisten Bücher dargestellt ist, dass Component die Methoden eines Composite hat. Ich denke, das liegt wahrscheinlich daran, dass das Muster ziemlich alt ist und seit Jahren so wiederholt wird. Meine Annahme ist, dass nur die Composite irgendwelche Methoden zum Compositing haben sollte.

Ich habe einmal ein Brettspiel in ein Computerspiel umgewandelt. Die Spielsteine ​​wurden auf eine in Sechsecke aufgeteilte Erdkarte gelegt. 99% aller Sechsecke repräsentierten einen einzigen Ort. Leider enthielten einige der Sechsecke mehrere Orte, einige hatten zum Beispiel ein paar Inseln in ihnen. Ich habe das zusammengesetzte Muster verwendet, um diese Orte darzustellen, aber nicht wie auf Ihrem Link dargestellt. Es war so etwas wie dieses (in Java):

public interface Location { 
    Set<Army> getArmies(); 
} 

public class SingleLocation implements Location { 

    public Set<Army> getArmies() { 
     return armies ; 
    } 

    private Set<Army> armies = new HashSet<Army>(); 
} 

public class CompositeLocation implements Location { 

    public Set<Army> getArmies() { 

     Set<Army> armies = new HashSet<Army>(); 

     for(Location subLocation: subLocations) { 
     armies.addAll(subLocation.getArmies()); 
     } 

     return armies; 
    } 

    public void addSubLocation(Location location) { 
     subLocations.add(location); 
    } 

    private Set<Location> subLocations = new HashSet<Location>(); 
} 

Beachten Sie, dass nur die Composite Compositing Methoden hat, und setzen nicht einmal die Tatsache, dass es Kinder auf die meisten Kunden (in diesem Beispiel, nur der Kunde will eine Liste der Armeen von einem Ort aus - die Tatsache, dass sie sich an vielen Unterstandorten befinden, ist irrelevant.

Denken Sie daran, Design-Muster sind nicht in Stein gemeißelte Dinge, die Sie genau umsetzen müssen. Denken Sie an sie als Rezepte. Wenn du beim Kochen einem Rezept folgst, kannst du es sicher genau befolgen. Einige Köche werfen jedoch ihre eigenen Wendungen auf das Rezept. Andere werden es nicht einmal anschauen, weil sie Experten sind und etwas zusammen in den Geist des Rezepts werfen können, ohne darüber nachzudenken. Das Gleiche gilt für Designmuster. Sie sind formbare Rezepte.

Sie können diese SOLID-Prinzipien auch zu weit führen. Wenn Sie die Artikel von Robert Martin lesen, stellt er fest, dass die unkonventionelle Anwendung der Prinzipien übermäßig komplexen Code ergibt. Software wird durch eine Reihe von Trade-Offs und Balancings entwickelt - manchmal verzichten Sie auf reinen SOLID, weil er saubereren, weniger komplexen Code liefert. Wenn Sie Ihren Code perfekt gekapselt, flexibel, entkoppelt, usw. machen würden, hätten Sie eine neue Programmiersprache erfunden :-)

+0

Das ist sehr üblich, aus guten Gründen - aber es gibt Gründe für die Standardversion. Zum Beispiel können die Elemente neben dem einfachen Compositing funktionale Abhängigkeiten zueinander haben - die Höhe eines Absatzes hängt beispielsweise von der Höhe jeder Textzeile ab, die von der Höhe jedes Zeichens innerhalb der Zeile abhängt. Wenn ein separater Hashwert verwendet wird, müssen die zusammengesetzten Elemente auf den Verbund verweisen, um ihre unmittelbaren Verwandten zu finden. Natürlich hat dies auch Vorteile - und die Zusammensetzung kann die Verantwortung für Teilbaumzusammenfassungen wie die Absatzhöhe übernehmen. – Steve314

5

Ich würde sagen, dass das Composite-Muster, wie in Ihrem Link beschrieben, die Liskov substitution principle, eine der die fünf SOLID Prinzipien.

Component hat Methoden, die nur für einen Composite z. Add(). Leaf erbt von Component, so wird es eine Add() Methode wie jede andere Component haben. Aber Leafs haben keine Kinder, so kann die folgende Methodenaufruf kein sinnvolles Ergebnis zurück:

myLeaf.Add(someChild);

Diese Forderung wäre eine MethodNotSupportedException zu werfen haben, kehren null oder angeben, auf andere Weise zu dem Anrufer, dass das Hinzufügen ein Kind zu einem Leaf macht keinen Sinn.

Daher können Sie keine Leaf wie jede andere Component behandeln, weil Sie eine Ausnahme erhalten, wenn Sie es versuchen.Das Liskov Substitutionsprinzip besagt:

q (x) Es sei eine Eigenschaft sein sollte beweisbar über Objekte x vom Typ T Dann q (y) für Objekte y vom Typ S wahr sein, wo S ein Subtyp von T.

Components haben die Eigenschaft, dass Sie ihnen Kinder hinzufügen können. Aber Sie können keine Kinder zu einem Leaf hinzufügen, obwohl Leaf ein Untertyp von Component ist, der das Prinzip verletzt.

+0

Ein Typ muss von der semantischen Interoperabilität mit seinem übergeordneten Typ abweichen, um als Verletzung des Llisk-Substitutionsprinzips zu gelten. Wenn der Leaf-Typ dies tut, dann wäre dies auf die Unfähigkeit zurückzuführen, Add() mit einem Kind aufzurufen und anschließend aufzurufen GetChild() mit dem erwarteten Index. Das bloße Weglassen von Verhalten würde jedoch nicht als Verletzung angesehen. Die Add() - Methode hat keinen impliziten oder expliziten Vertrag, der eine Rückmeldung darüber erfordert, dass das Kind hinzugefügt wurde. Es gibt jedoch einen impliziten Vertrag, der davon ausgeht, dass ein hinzugefügtes Kind von der GetChild() -Methode abgerufen werden kann. –

+0

Übrigens ist der Grund, warum das Null-Objekt-Muster wirksam ist, darin begründet, dass es das Verhalten unter Beibehaltung der semantischen Interoperabilität auslässt. –

0

Mit Composite können Sie alle Objekte gleichmäßig behandeln und möglicherweise "instanceOf" -Ding loswerden, was ein klares Zeichen für einen Code-Geruch ist. Es entspricht also LSP (Liskovs) auf den ersten Blick. Wenn Sie jedoch allgemeine Methodenimplementierungen unterscheiden, wird wahrscheinlich LSP verletzt. Also, IMO, wir müssen dieses Gleichgewicht halten.

Verwandte Themen