2009-10-16 19 views
9

la hoja en el material compuesto implementa el componente que tiene la GetChild métodos Add quita y que nunca se va a utilizar (violación de la segregación Interface)¿El patrón compuesto es SÓLIDO?

también lo es el uso de patrón compuesto SOLID?

enlace al compuesto http://www.dofactory.com/Patterns/PatternComposite.aspx

+0

Su pregunta no está clara. Además, ¿qué quiere decir con "SOLIDO" – monksy

+0

Agregué un enlace SOLIDO para el interrogador, arriba. – SingleShot

+0

SRP y LSP también se violan junto con ISP. Entonces SOLIDO es peligroso. :) – Narek

Respuesta

10

El olor real en el patrón como se muestra en su enlace y la mayoría de los libros es que Component tiene los métodos de una Composite. Creo que esto es probablemente porque el patrón es bastante viejo y se ha repetido de esa manera durante años. Mi opinión es que solo el Composite debe tener algún método relacionado con la composición.

Una vez convertí un juego de mesa en un juego de computadora. Las piezas de juego se colocaron en un mapa de la tierra, divididas en hexágonos. El 99% de todos los hexágonos representaban una sola ubicación. Desafortunadamente, algunos de los hexágonos contenían múltiples ubicaciones, por ejemplo, algunos tenían un par de islas dentro de ellos. Usé el patrón compuesto para representar estas ubicaciones, pero no como se muestra en su enlace. Era algo como esto (en 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>(); 
} 

Tenga en cuenta que sólo el Composite tiene métodos de composición, e incluso no exponga el hecho de que tiene los niños a la mayoría de los clientes (en este ejemplo, el cliente sólo quiere una lista de ejércitos desde una ubicación; el hecho de que se encuentren en muchas sublocaciones es irrelevante).

Tenga en cuenta que los patrones de diseño no son cosas inamovibles que debe implementar exactamente. Piense en ellos como recetas. Cuando sigues una receta mientras cocinas, puedes seguirla exactamente. Sin embargo, algunos cocineros darán sus propios giros a la receta. Otros ni siquiera lo mirarán porque son expertos y pueden armar algo en el espíritu de la receta sin siquiera pensar en ello. Lo mismo ocurre con los patrones de diseño. Son recetas maleables.

También puede tomar esos principios SÓLIDOS demasiado lejos. Si lees los artículos de Robert Martin, él afirma que aplicar los principios en todos los ámbitos sin pensarlo supondrá un código excesivamente complejo. El software está diseñado a través de una serie de compensaciones y equilibrios: a veces se renuncia al SOLIDO puro porque produce un código menos complejo y menos contaminante. Si tu código fuera perfectamente encapsulado, flexible, desacoplado, etc., habrás inventado un nuevo lenguaje de programación :-)

+0

Eso es muy común, por buenas razones, pero hay razones para la versión estándar. Por ejemplo, los elementos pueden tener dependencias funcionales entre sí además de la composición simple: la altura de un párrafo, por ejemplo, depende de la altura de cada línea de texto, que depende de la altura de cada carácter dentro de la línea. Usar un hash separado significa que los elementos compuestos deben referirse de nuevo al compuesto para encontrar a sus parientes inmediatos. Por supuesto, esto también tiene sus ventajas, y el compuesto puede asumir la responsabilidad de los resúmenes de subárboles como la altura de ese párrafo. – Steve314

5

Yo diría que el patrón compuesto como se describe en tu enlace infringe el Liskov substitution principle, uno de los cinco principios SOLID.

Component tiene métodos que solo tienen sentido para un Composite p. Add(). Leaf hereda de Component por lo que tendrá un método Add() como cualquier otro Component. Pero Leafs no tienen hijos, por lo que la siguiente llamada al método no puede devolver un resultado significativo:

myLeaf.Add(someChild);

Esa llamada tendría que lanzar una MethodNotSupportedException, volver null o indique de otra manera a la persona que llama que la adición un niño a un Leaf no tiene sentido.

Por lo tanto, no puede tratar un Leaf como cualquier otro Component porque obtendrá una excepción si lo intenta.Los Liskov principio SUSTITUCIÓN estados:

Sea Q (x) sea una propiedad demostrable sobre objetos x de tipo T. Entonces q (y) debe ser cierto para los objetos y de tipo S donde S es un subtipo de T.

Components tienen la propiedad de que usted puede agregar niños a ellos. Pero no puede agregar hijos a un Leaf, aunque Leaf es un subtipo de Component, lo que infringe el principio.

+0

Un tipo tiene que desviarse de la interoperabilidad semántica con su tipo padre para calificar como una violación del Principio de sustitución Liskov, por lo que si el tipo Leaf lo hace, entonces sería debido a la incapacidad de llamar a Add() con un hijo y posteriormente llamar GetChild() con el índice esperado. Sin embargo, la mera omisión del comportamiento no calificaría como una violación. El método Add() no tiene ningún contrato implícito o explícito que exija que proporcione comentarios sobre la adición del elemento secundario, pero existe un contrato implícito que supone que el método GetChild() puede recuperar un elemento secundario adicional. –

+0

Por cierto, la razón por la cual el patrón de Objeto Nulo es efectivo es porque omite el comportamiento mientras se mantiene la interoperabilidad semántica. –

0

El uso de Composite le permite tratar todos los objetos de manera uniforme y posiblemente deshacerse de la característica "instanceOf", que es una clara señal de olor a código. Entonces, es respetuoso con LSP (Liskov's) a primera vista. Sin embargo, a medida que diferencia las implementaciones de métodos comunes, es probable que comience a violar el LSP. Entonces, OMI, necesitamos mantener ese equilibrio.

Cuestiones relacionadas