Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the Composite Pattern SOLID?

A Leaf in the Composite Pattern implements the Component interface, including Add, Remove, and GetChild methods that a Leaf is never going to use. This seems to be a violation of the Interface Segregation Principle.

So is the usage of Composite Pattern SOLID?

link to Composite Pattern: http://www.dofactory.com/Patterns/PatternComposite.aspx

like image 884
Omu Avatar asked Oct 16 '09 18:10

Omu


People also ask

What type of pattern is composite pattern?

In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes a group of objects that are treated the same way as a single instance of the same type of object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies.

What is unique about the composite pattern?

It allows you to have a tree structure and ask each node in the tree structure to perform a task. As described by Gof, “Compose objects into tree structure to represent part-whole hierarchies. Composite lets client treat individual objects and compositions of objects uniformly”.

Is composite pattern good?

The Composite pattern lets you run a behavior recursively over all components of an object tree. The greatest benefit of this approach is that you don't need to care about the concrete classes of objects that compose the tree. You don't need to know whether an object is a simple product or a sophisticated box.

What is the composite pattern used for?

Composite pattern is used where we need to treat a group of objects in similar way as a single object. Composite pattern composes objects in term of a tree structure to represent part as well as whole hierarchy.


2 Answers

The GoF book specifically addresses this issue on page 167.

Although the Composite class implements the Add and Remove operations for managing children, an important issue in the Composite pattern is which classes declare these operations... Should we declare these operations in the Component and make them meaningful for Leaf classes, or should we declare and define them only in Composite?

The decision involves a trade-off between safety and transparency:

  • Defining the child management interface at the root of the class hierarchy gives you transparency, because you can treat all components uniformly. It costs you safety, however, because clients may try to do meaningless things like add and remove objects from leaves.
  • Defining child management in the Composite class gives you safety, because any attempt to add or remove objects from leaves will be caught at compile-time in a statically typed language like C++. But you lose transparency, because leaves and composites have different interfaces.

We have emphasized transparency over safety in this pattern.

The last sentence is an admission that the pattern violates type-safety principles. In terms of SOLID, this would primarily be LSP, but possibly ISP as well. Note that "declaring methods which a subclass doesn't use" is an oversimplification of ISP. The real danger of those unused methods is that they will require additional dependencies which the subclass didn't need, increasing coupling between modules.

like image 144
jaco0646 Avatar answered Sep 23 '22 20:09

jaco0646


I would say that the Composite pattern as described in your link violates the Liskov substitution principle, one of the five SOLID principles.

Component has methods that only make sense for a Composite e.g. Add(). Leaf inherits from Component so it will have an Add() method like any other Component. But Leafs don't have children, so the following method call cannot return a meaningful result:

myLeaf.Add( someChild );

That call would have to throw a MethodNotSupportedException, return null or indicate in some other way to the caller that adding a child to a Leaf does not make sense.

Therefore you cannot treat a Leaf like any other Component because you'll get an exception if you try to. The Liskov substition principle states:

Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.

Components have the property that you can add children to them. But you cannot add children to a Leaf, even though Leaf is a subtype of Component, which violates the principle.

like image 23
ctford Avatar answered Sep 23 '22 20:09

ctford