tags:

views:

55

answers:

2

Given a leaf, and its parent TD, do a print:

$parent = new Node('td');
$child = new Leaf('Text:', 'Value');
$parent->add($child);
$parent->print();

print requirement:

sometimes <td>Text: Value</td>
sometimes <td>Text:</td><td>Value</td>

So far i constructed 3 solutions, but none satisfied me, i wonder which one is more OO? And is there a 4th choice?

-- Solution 1 --
// Divide the leaf object to two leaf objects
$leafText = new Leaf('Text: ');
$leafvalue = new Leaf('Value');
$parent->add($leafText);
$parent->add($leafValue);
$parent->print();

-- Solution 2 --
// Change leaf print() logic, if leaf's parent is TD, output "Text: Value",
// otherwise output "<td>Text:</td><td>Value</td>"

-- Solution 3 --
// Change parent add() logic, give leaf a variable $separate to describe if it 
// should be divided
function add($child) {
    if($child->separate) {
        $this->parent->add($child->text);
        $this->children[] = $child->value;
    }
    ...
}
A: 

I'd have to go with solution 2 personally. You say that with that solution a leaf can hold a node, which you don't like, but is there any reason it has to be able to hold a node? Since you're using different classes (Node and Leaf) you should be able to add a check that prevents passing a Node into the Leaf (something like this):

class Leaf {
  public function __construct($text, $value) {
    if (is_object($text))
      throw new Exception('error message');

    if (get_class($value) == 'Node')
      throw new Exception('error message');
  }
}

Both of those checks should work, the second one is just checking for a specific class while the first one just prevents all objects. You could also use the is_string() function, but that will disallow ints.

Steven Surowiec
get it, 2 is better, right? but why? type checking is not a problem cos i use composite pattern, thanks for reminder.
Edward
2 is the most simple ... but not very clean, really ...
back2dos
i worked out the 4th solution, base on solution 2, just a little modification, now i think it is the best solution
Edward
+1  A: 

most OO would be to seperate rendering logic from data model ... your model hierarchy should be traversible by a controller, that'd render your data into a view hierarchy ...

also, "chain of control" should follow your hierarchy ... it's not up to the leaf determining its behaviour depending on the parent, it's up to the parent to get info from the leaf, and then process it depending on it's own state, or to pass necessary data to the child when querying for any sort of information ... that way the leaf is decoupled from the node ... otherwise you have a two-way dependancy, which greatly decreases reusability ...

back2dos
useful description, i'm trying to understand. i ever thought about add a controller, and even thought about remove TD from hierarchy. So far i'm yet looking for an elegant, or clean in your words, way for solving this problem
Edward
Great, your answer helps to make problem clear. Cos by using Composite pattern, each node/leaf already knows how to print itself and do process print itself. But to meet the requirement in question, node/leaf could no longer be kept alone, in 2nd solution, leaf have to know parent info; in 3nd solution, parent have to know child info; both introduce additional dependansy. Now i know why neither solution makes me comfortable. Add a controller seems no help, really a brain ache
Edward