Composite As Ring

There is some question as to whether the Composite Pattern must be a heirarchincal "tree" or can be another structure, such as a ring or a web.

It seemed to me that it might be useful to show a concrete code example for discussion. Here is a Composite pattern using a Ring. The code is for demonstration only, but it does compile and run (it's Java), and does show (I think) that the Composite can be implemented with varying structure.

Composite as ring 1

/**
* Example of a Ring Composite
*
* @author Scott
* @version 1.0
*/
public abstract class Component
{
     public abstract int getValue();
     protected abstract int getBestValue(int bestValueSoFar, Component token);
}


public class SimpleComponent extends Component
{
     private int myValue = java.util.Random().nextInt();
     public SimpleComponent(){}

     public int getValue()
     {
          return myValue;
     }

     protected int getBestValue(int bestValueSoFar, Component token)
     {
          if(getValue() > bestValueSoFar) return getValue();
          return bestValueSoFar;
     }
}

public class RingComponent extends Component
{
     private Component nextComponent;
     private int myValue;
     public RingComponent(int aValue)
     {
          myValue = aValue;
     }

     public void setNextComponent(Component aNextComponent)
     {
          this.nextComponent = aNextComponent;
     }

     public int getValue()
     {
          return getBestValue(myValue, null);
     }

     protected int getBestValue(int bestValueSoFar, Component token)
     {
          if(myValue > bestValueSoFar) bestValueSoFar = myValue;
          if(token == this)
          {
               return bestValueSoFar;
          } else {
               if(token == null)
               {
                    return nextComponent.getBestValue(bestValueSoFar, this);
               } else {
                    return nextComponent.getBestValue(bestValueSoFar, token);
               }
          }
     }
}

public class Client
{
     private Component myComponent;

     public Client()
     {
          ComponentFactory factory = ComponentFactory.getInstance();
          myComponent = factory.getComponent();
     }

     public void process()
     {
          System.out.println("Value:" + myComponent.getValue());
     }

     public static void main(String[] args)
     {
          Client c = new Client();
          c.process();
     }
}

public class ComponentFactory
{
     private static ComponentFactory _instance = new ComponentFactory();
     private ComponentFactory(){}
     public static ComponentFactory getInstance(){return _instance;}
     public Component getComponent()
     {
          // Alternate factory implementation:
          // return new SimpleComponent();

          // Change the values given to each RingComponent in the constuctor
          // The highest-valued component will always self-select
          RingComponent ComponentA = new RingComponent(2);
          RingComponent ComponentB = new RingComponent(3);
          RingComponent ComponentC = new RingComponent(1);
          RingComponent ComponentD = new RingComponent(4);

          // This code creates the Ring, making each entity "its own grandparent"
          ComponentA.setNextComponent(ComponentB);
          ComponentB.setNextComponent(ComponentC);
          ComponentC.setNextComponent(ComponentD);
          ComponentD.setNextComponent(ComponentA);

          return ComponentA;
     }
}

The reason I would call this a Composite is that the Client can interact with either the SimpleComponent or a set of RingComponents without taking any different action, so long as their construction is done in another entity (ComponentFactory). These differences are encapsulated, as is the specific behavior of the RingComponent, and the nature of the structure. These are all forces of the Composite Pattern.

Composite as ring 2

The request getValue() is implemented in SimpleComponent simply (just a random value in this case) whereas the RingComponent sends the request around the ring, with a token to sense when the traversal is complete. Each RingComponent instance holds state, and compares its value with the value traversing the ring, and replaces it if its value is greater. The elected "greatest value" is then returned to the Client. Only the ComponentFactory has visibility on any of the differences between these Components.

The Client could, by the way, be given a reference to any single instance in the ring, and the behavior would still work but with a different starting point. In this case the "highest value" would be the same regardless, because there is no persistent effect from one RingComponent's evaluation to another, but that's just because the implementation here is very straightforward. "Where we start" is an issue also encapsulated from the Client, which is similar to the issue of composite trees, that allow the Client to start "somewhere down the tree" in the same way as it would starting from the top.

In fact, the Ring could be interrupted (not complete) by giving one of the RingComponents a SimpleComponent to delegate to. This would create a non-looping chain of objects (similar to a Chain of Responsibility) with, again, no difference in the Client. We could "force" the Ring to be complete by moving the containment relationship down from the abstract Component class to the concrete RingComponent class. Again, the Client would not change.

This is obviously a very simplified example, but it shows, I think, that a Composite does not have to be a tree.

-Scott-