---
title: "SP3 - Tree - Learn Design Pattern From Simple Things"
description: "You need to store the leaves hierarchically, sometimes you will count the leaves. Tree will be a suitable structure to facilitate leaf counting."
pubDate: "2023-01-01"
lang: "en"
slug: "sp3-tree-learn-design-pattern-from-simple-things"
url: "https://hoangyell.com/sp3-tree-learn-design-pattern-from-simple-things/"
author: "HoangYell"
categories: ["Software Craft"]
tags: ["design-patterns", "structural-patterns"]
heroImage: "https://raw.githubusercontent.com/HoangGeek/store/main/webp/72PIGmm.webp"
---

_Tree (Composite) is a **structural** design pattern:_
🖤🖤🖤🖤🖤

## What is Tree?

Tree is an object that contains Branches and Leaves. We can recursively over the whole tree structure and sum up the results easily.

![Image](https://raw.githubusercontent.com/HoangGeek/store/main/webp/210161906-3c5d8744-8b5f-4f96-bc24-21f043fce85b.webp)

## Why use Tree?
It's neat and clean as you traverse the entire tree to find what you need.
You have no choice but it!

![Image](https://raw.githubusercontent.com/HoangGeek/store/main/webp/5f9c9f48740569d1a4ca41c4.webp)

**Question:** _`Branch` is like a container, right? How about using the `list` to store `leaves`?_

**Answer:** _`Branch` is like a container, but it has a method(`def operation`, Same name as leaf's method) that can delegate the work to all leaves in it. Thus, it is possible to traverse all the leaf's methods(operations)_

## When to use Tree?
**Question:** _When do I need to use `Tree`?_

**Answer:** _When you want to store the leaves hierarchically. Then want to traverse and use the method of leaves(operations)?_

### Input:
  - Having many leaves.
  - Having the hierarchy of those leaves.

``` python
class Leaf:
    def operation(self):
        return "🍁"

container_1 = []
container_1.append(Leaf())
container_1.append(Leaf())
container_2 = []
container_2.append(Leaf())
wormy_leaf = Leaf()

containers = []
containers.append(container_1)
containers.append(Leaf())
containers.append(wormy_leaf)
containers.append(container_2)
containers.remove(wormy_leaf)
```
### Expected Output:
  - All leaves are stored hierarchically in an object
  - Show the operation of all leaves
``` shell
[['🍁', '🍁'], '🍁', ['🍁']]
```

## How to implement Tree?

### Non-Tree implementation:
``` python
class Leaf:
    def operation(self):
        return "🍁"

def platten(nested_list):
    results = []
    for item in nested_list:
        item_result = platten(item) if isinstance(item, list) else item.operation()
        results.append(item_result)
    return results

if __name__ == "__main__":
    container_1 = []
    container_1.append(Leaf())
    container_1.append(Leaf())

    container_2 = []
    container_2.append(Leaf())

    wormy_leaf = Leaf()

    containers = []
    containers.append(container_1)
    containers.append(Leaf())
    containers.append(wormy_leaf)
    containers.append(container_2)
    containers.remove(wormy_leaf)

    print(platten(containers))
```

### Tree Implementation:
``` python
from abc import ABC, abstractmethod

class Component(ABC):
    _parent = None

    @property
    def parent(self):
        return self._parent

    @parent.setter
    def parent(self, parent):
        self._parent = parent

    def add(self, component):
        pass

    def remove(self, component):
        pass

    @abstractmethod
    def operation(self):
        pass

class Leaf(Component):
    """
    A leaf can't have any children.
    Leaf objects do the actual work.
    """

    def operation(self):
        return "🍁"

class Branch(Component):
    """
    A branch can have children(leaves or baby branches) .
    Branch objects do nothing but contain children
    """

    def __init__(self):
        self._children = []

    def add(self, component):
        component.parent = self
        self._children.append(component)

    def remove(self, component):
        component.parent = None
        self._children.remove(component)

    def operation(self):
        results = []
        for child in self._children:
            results.append(child.operation())
        return results

if __name__ == "__main__":
    branch_1 = Branch()
    branch_1.add(Leaf())
    branch_1.add(Leaf())

    branch_2 = Branch()
    branch_2.add(Leaf())

    wormy_leaf = Leaf()

    tree = Branch()
    tree.add(branch_1)
    tree.add(Leaf())
    tree.add(wormy_leaf)
    tree.add(branch_2)
    tree.remove(wormy_leaf)

    print(tree.operation())
```

[Source Code](https://github.com/HoangYell/Design-Pattern-From-Simple-Things/blob/main/sp3_tree.py)
