I’m studying and implementing the Composite design pattern in C# for a university project.

In most textbook examples (GoF, Refactoring.Guru, etc.) the class hierarchy looks like this:

Component
 ├── Leaf
 └── Composite

However, in my actual application, components also need a common Id property because they must be persisted (XML database) and use it like Generic on various Managers classes.

So instead of making Component the root class, I have this:

public abstract class EntityBase
{
    public int Id { get; set; }
}
  
public abstract class Component : EntityBase
{
    public string Name { get; set; }
  
    public virtual bool IsLeaf => true;
  
    public virtual IReadOnlyList<Component> Children => Array.Empty<Component>();
}
  
public class Permission : Component  // Leaf
{
}
  
public class Role : Component        // Composite
{
    private List<Component> _children = new();
  
    public override bool IsLeaf => false;
}

My professor claims that this implementation "breaks" the composite pattern because:

"Component should not inherit from anything else."

"Component must be the top-most root of the hierarchy."

I cannot find any support for that in the original GoF book.

Does the composite pattern require component to be the root of the inheritance hierarchy?

Or is it acceptable for component to inherit from another abstract base class (e.g., EntityBase that only provides an Id) without violating the composite design principles?

I am looking for:

  • citations from design pattern references (GoF, Fowler, Gamma, etc.).
  • examples of real-world implementations.
  • clarification about whether this breaks the pattern or is perfectly fine.

Thanks!

3 Replies 3

Just a note, without any judgement on your idea: if some really good and well-maintainable technique voolates some design pattern, its no good for this pattern, not for your code.

Everyone needs to realize that design patterns are published and tought to help projects. Not that projects are designed to please the authors of design patterns.

Please don't get me wrong: I don't want to say a single word in favor or against your idea of this particular case of inheritance. I just say that violaton of a design pattern is not a crime. It can be a crime when the violation really harms your code design.

If your professor says it violates the pattern, they've already given you all the clarification you need for the purposes of the assignment. That is, you've been informed (warned, really) that you're very likely to lose marks/credit if you do it.

Does the Composite pattern require Component to be the root of the inheritance hierarchy?

Within the narrow definition of the pattern, yes. Specifically, the client to this pattern must interact with the Component interface. In the GoF book this is shown graphically on the bottom of page 164 and spelled out on the bottom of page 165.

Clients use the Component class interface to interact with objects in the composite structure.

It's probably obvious to you that the design pattern client cannot interact directly with your EntityBase and that any methods expecting a Component would not accept an EntityBase either. I'm sure you never intended or expected to use the EntityBase that way anyway, but I suspect your professor may want to eliminate any possible confusion by prohibiting classes that add unnecessary "noise" from the narrow perspective of one specific design pattern.

So if you were writing a book on design patterns, you would avoid adding any additional base class that could confuse readers about necessary versus unnecessary elements of the pattern. But if you're coding in the real world, then of course every pattern will need to be incorporated into a domain of context. EntityBase is a part of that real-world context, not part of the pattern. I personally would not describe this addition as "breaking" the pattern; but hopefully you can see why an instructor would want to avoid any extraneous elements that could potentially confuse the fundamentals of the pattern itself.

TLDR: EntityBase does not prevent the Composite Pattern from being used through the Component interface as intended, but the pattern cannot be used through the EntityBase.

Your Reply

By clicking “Post Your Reply”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.