10.1. Composite¶
EN: Composite
PL: Kompozyt
Type: object
10.1.1. Pattern¶
Represent a hierarchy of objects
Groups (and subgroups) objects in Keynote
Files in a Folder; when you move folder you also move files
allows you to represent individual entities and groups of entities in the same manner.
is a structural design pattern that lets you compose objects into a tree.
is great if you need the option of swapping hierarchical relationships around.
makes it easier for you to add new kinds of components
conform to the Single Responsibility Principle in the way that it separates the aggregation of objects from the features of the object.

10.1.2. Problem¶

from dataclasses import dataclass, field
class Shape:
def render(self) -> None:
print('Render Shape')
@dataclass
class Group:
objects: list[Shape | 'Group'] = field(default_factory=list)
def add(self, obj: Shape|'Group') -> None:
self.objects.append(obj)
def render(self) -> None:
for obj in self.objects:
obj.render()
if __name__ == '__main__':
group1 = Group()
group1.add(Shape()) # square
group1.add(Shape()) # square
group2 = Group()
group2.add(Shape()) # circle
group2.add(Shape()) # circle
group = Group()
group.add(group1)
group.add(group2)
group.render()
10.1.3. Solution¶

from abc import ABC, abstractmethod
from dataclasses import dataclass, field
class Component(ABC):
@abstractmethod
def render(self) -> None:
pass
@abstractmethod
def move(self) -> None:
pass
class Shape(Component):
def move(self) -> None:
print('Move Shape')
def render(self) -> None:
print('Render Shape')
@dataclass
class Group(Component):
components: list[Component] = field(default_factory=list)
def add(self, component: Component) -> None:
self.components.append(component)
def render(self) -> None:
for component in self.components:
component.render()
def move(self) -> None:
for component in self.components:
component.move()
if __name__ == '__main__':
group1 = Group()
group1.add(Shape()) # square
group1.add(Shape()) # square
group2 = Group()
group2.add(Shape()) # circle
group2.add(Shape()) # circle
group = Group()
group.add(group1)
group.add(group2)
group.render()
group.move()
10.1.4. Assignments¶
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
class Shape(ABC):
@abstractmethod
def print(self):
pass
class Ellipse(Shape):
def print(self):
print('Ellipse')
class Circle(Shape):
def print(self):
print('Circle')
@dataclass
class Group(Shape):
children: list = field(default_factory=list)
def add(self, graphic):
self.children.append(graphic)
def print(self):
for children in self.children:
children.print()
if __name__ == '__main__':
group1 = Group()
group1.add(Ellipse())
group2 = Group()
group2.add(Circle())
group2.add(group1)
group2.print()