Last active
July 3, 2019 07:31
-
-
Save NargiT/de4555c59e0e9437a3c8c6c22960edc2 to your computer and use it in GitHub Desktop.
Design Pattern - Composite
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import abc | |
from typing import Dict, Optional, Sequence | |
class Component(metaclass=abc.ABCMeta): | |
@property | |
@abc.abstractmethod | |
def name(self): | |
pass | |
@property | |
@abc.abstractmethod | |
def parent(self): | |
pass | |
@property | |
def path(self): | |
return Component._recursive_path(self.parent, self.name) | |
@staticmethod | |
def _recursive_path(parent: 'Component', right_part: str): | |
if parent is None: | |
return "/" + right_part | |
else: | |
return Component._recursive_path(parent.parent, parent.name + "/" + right_part) | |
class Composite(Component): | |
_nodes: Dict[str, Component] | |
_parent: 'Composite' | |
_name: str | |
def __init__(self, name: str, parent: Optional['Composite'] = None): | |
self._name = name | |
self._nodes = {} | |
self._parent = parent | |
@property | |
def name(self): | |
return self._name | |
@property | |
def parent(self): | |
return self._parent | |
def add(self, node: Component): | |
if self._nodes.get(node.name) is not None: | |
pass | |
else: | |
self._nodes[node.name] = node | |
node._parent = self | |
def find(self, name: str) -> Optional[Component]: | |
return self._nodes.get(name) | |
@property | |
def nodes(self) -> Sequence[Component]: | |
return list(self._nodes.values()) | |
class Leaf(Component): | |
_name: str | |
_content: str | |
_parent: Composite | |
def __init__(self, name: str, content: str): | |
self._content = content | |
self._name = name | |
@property | |
def name(self): | |
return self._name | |
@property | |
def parent(self): | |
return self._parent | |
class Name: | |
_value: str | |
def __init__(self, path: str): | |
split = path.split("/") | |
self._value = split[split.__len__() - 1] | |
@property | |
def value(self): | |
return self._value | |
def test_tree(): | |
folder = Composite('a') | |
file = Leaf('stuff', 'a file with stuff') | |
file1 = Leaf('stuff1', 'a file with stuff1') | |
folder.add(file) | |
folder.add(file1) | |
file2 = Leaf('stuff2', 'a file with stuff2') | |
folder2 = Composite('sub-folder', folder) | |
folder2.add(file2) | |
folder.add(folder2) | |
assert folder.name == 'a' | |
assert folder.path == '/a' | |
assert folder.nodes[0].name == 'stuff' | |
assert folder.nodes[0].path == '/a/stuff' | |
assert folder.nodes[1].name == 'stuff1' | |
assert folder.nodes[1].path == '/a/stuff1' | |
assert folder.nodes[2].name == 'sub-folder' | |
assert folder.nodes[2].path == '/a/sub-folder' | |
assert cast(Composite, folder.nodes[2]).nodes[0].name == 'stuff2' | |
assert cast(Composite, folder.nodes[2]).nodes[0].path == '/a/sub-folder/stuff2' | |
def test_simple(): | |
folder = Composite('a') | |
assert folder.path == '/a' | |
def test_simple_with_file(): | |
folder = Composite('a') | |
file = Leaf('b', 'stuff') | |
folder.add(file) | |
assert folder.path == '/a' | |
assert file.path == '/a/b' | |
def test_name(): | |
name = Name('/toto/pat') | |
assert 'pat' == name.value | |
def test_simple_name(): | |
name = Name('toto') | |
assert 'toto' == name.value | |
def test_simple_name2(): | |
name = Name('') | |
assert '' == name.value | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment