Java – Multi-leaf approach problem in composite patterns

Multi-leaf approach problem in composite patterns… here is a solution to the problem.

Multi-leaf approach problem in composite patterns

At work, we are developing a PHP application that will later be reprogrammed into Java. With some Java basics, we’re trying to design everything to be easy to rewrite without headaches. When we try to implement a composite pattern interesting problems arise in the leaf.

What we’re trying to implement (not using an interface, this is just a simple example):

class Composite {
    ...
}

class LeafOne {
    public function Foo( );

public function Moo( );
}

class LeafTwo {
    public function Bar( );

public function Baz( );
}

$c = new Composite( Array( new LeafOne( ), new LeafTwo( ) ) );

 will call method Foo in all classes in composite that contain this method
$c->Foo( );

 same with Bar
$c->Bar( );

This looks a lot like the classic composite pattern, but the problem is that we will have a lot of leaf classes, each of which may have about 5 methods (very few of which have the potential to differ from the others). One of our solutions is to use the __call magic method, which seems to be the best so far and probably really works. Call the method in the leaf.
Unfortunately, we don’t know if there is an equivalent in Java.

So the practical question is: is there a better solution to use code that can end up being easily recoded into Java? Or do you recommend any other solution? Maybe I can use some different, better patterns here.

If anything is unclear, just ask, I’ll edit this article.

Edit:

The practical problem is that not every leaf class contains a method Baz. If we call Baz in each class with a simple foreach, it produces a bunch of errors because some classes don’t include this method. The classic solution is to implement each method in each leaf class into the Composite class, and each method has a different implementation. But this makes our composite classes huge and confusing because we use a lot of methods.

The usual solution looks like this (composite class):

class Composite implements Fooable, Bazable {
    ...

public function Foo( ) {
        foreach( $this->classes as $class ) {
            $class->Foo( );
        }
    }

public function Baz( ) {
        ...
    }
}

To prevent our code from getting really confused, we’re thinking about something like this:

class Composite {
    ...

public function __call( ) {
         implementation
    }
}

But we’re not sure if it’s a good solution and if there’s something similar in Java (as already asked before editing).

Solution

In Java, you might consider using the visitor pattern, where you pass a visitor object to each node in the tree, which then makes a visit class to each node callback to determine which behavior should be performed.

This avoids any conversion or explicit checking of each node’s type.

/**
 * Visitor capable of visiting each node within a document.
 * The visitor contains a callback method for each node type
 * within the document.
 */
public interface DocumentNodeVisitor {
  void visitWord(Word word);
  void visitImage(Image img);
}

/**
 * Base interface for each node in a document.
 */
public interface DocumentNode {
  void applyVisitor(DocumentVisitor v);
}

/**
 * Conrete node implementation representing a word.
 */    
public class Word implements DocumentNode {
  private final String s;

public Word(String s) { this.s = s; }

public String getValue() { return this.s; }

public void applyVisitor(DocumentVisitor v) {
     Make appropriate callback to visitor.
    v.visitWord(this);
  }
}

/**
 * Conrete node implementation representing an image.
 */        
public class Image implements DocumentNode {
  public void applyVisitor(DocumentVisitor v) {
     Make appropriate callback to visitor.
    v.visitImage(this);
  }
}

public class Paragraph implements DocumentNode {
  private final List<DocumentNode> children;

public Paragraph() {
    this.children = new LinkedList<DocumentNode>();
  }

public void addChild(DocumentNode child) {
     Technically a Paragraph should not contain other Paragraphs but
     we allow it for this simple example.
    this.children.add(child);
  }

 Unlike leaf nodes a Paragraph doesn't callback to
   the visitor but rather passes the visitor to each
   child node.
  public void applyVisitor(DocumentVisitor v) {
    for (DocumentNode child : children) {
      child.applyVisitor(v);
    }
  }
}    

/**
 * Concrete DocumentVisitor responsible for spell-checking.
 */
public class SpellChecker implements DocumentVisitor
  public void visitImage(Image i) {
     Do nothing, as obviously we can't spellcheck an image.
  }

public void visitWord(Word word) {
    if (!dictionary.contains(word.getValue()) {
       TODO: Raise warning.
    }
  }
}

Related Problems and Solutions