Elvex
Elvex

Reputation: 671

What is the correct design pattern to allow objects find their root in a hierarchal structure?

I have a hierarchical structure of objects (lets say, 3 levels).

Class A is composed with class B, class B with class C.

The initialization does something like :

$a1 = new A()
$a1->add('B1', $b11 = new B())
$a1->add('B2', $b12 = new B())
$b11->add('C1', $c111 = new C())
$b12->add('C1', $c121 = new C())
...

My problem occurs when $c121 wants to retrieve $c111. I currently know 2 ways to achieve that :

1/ Assume that A is a singleton : it gives me the ability to dash back to the root from any node of the tree. I can then address any node from the root with a full "pathname".

2/ Give to each object its ancestor, so they can go back (by ancestor reference) and forth (by pathname) through the tree.

While both serve my needs, I can't find any of those solutions satisfying.

Am I missing something ? This should be a common problem, yet I can't figure out what design pattern could match this issue.

EDIT Note that the hierarchy isn't composed of similar items. So it is a fixed hierarchy. Only the quantities of items at each level is fluctuating. (eg. Clients, Orders and Products Ordered)

Upvotes: 2

Views: 179

Answers (2)

ltiong_dbl
ltiong_dbl

Reputation: 3216

If your classes are disparate, then I'd treat them as such (ie you don't have a tree per se).
It seems like you're trying to treat the disparate elements as if they were somehow similar.

If you need access to a containing class (what you're calling parent), you will need to provide a reference.

In your example above, I would give your associated objects a reference to object "holding" it, and give the C class a means to get its siblings.

$c121=new C(this);   // pass reference to container
$c121->getSiblings();  // method to get sibling through reference to containing object

Another way to look at that is:

$frank=new Customer()
$frank->add('Order01', $order1 = new Order())
$frank->add('Order02', $order2 = new Order())
$order1->add('LineItem01', $item1 = new LineItem())
$order1->add('LineItem02', $item2 = new LineItem())

$order1->getOrder() //return collection
$order1->getOrder()->getItems() //return collection items/siblings

Upvotes: 1

Chris Gerken
Chris Gerken

Reputation: 16392

Do both. In Eclipse it's common for tools to implement a method on a known class that answers the model root. Objects that appear in trees (visually like tree items or implementation-wise like UI widget) all know their parents and can retrieve the parent through an inherited getParent() call.

Upvotes: 0

Related Questions