構造パターンの一つであるCompositeパターン
Compositeパターンとは
ツリー構造(階層構造)となるようにプログラミングするパターン。
どの節にどの葉を要素として追加していくのかを把握することが難しい場合、Compositパターンを用いてツリー構造を表現する。
(目的)
ツリー構造階層をわかりやすく表現する。
(仕組み)
葉(Reaf)と節(Composit)の共通機能を定義したComponetを作成する。
Componetを継承した、CompositとReafを作成する。
Compositをインスタンス化してそのCompositeの子要素とする。
Composit, Reafを追加していく。
(構成要素)
Component: CompositeとReafの共通機能を持った抽象クラス
Composite: 容器を表す役を持ったクラス。この中に、Composite,Reafを入れていき、
階層構造を作成する
Reaf: 中身を表す役のクラス。この中には要素を入れることができない。
サンプルプログラム
pythonによるCompositeパターンのサンプルプログラム。
ディレクトリの階層を表示する。
# composite.py
from abc import ABC, abstractmethod, abstractproperty
"""ディレクトリとファイルの構造を表現してみる"""
class Componet(ABC):
@abstractproperty
def name(self):
pass
@abstractproperty
def size(self):
pass
@property
def parent(self):
return self._parent
@parent.setter
def parent(self, parent):
self._parent = parent
@abstractmethod
def print_list(self, path):
pass
def __str__(self):
return f"{self.name} ({self.size})"
class File(Componet):
def __init__(self, name, size):
self.__name = name
self.__size = size
self._parent = None
@property
def name(self):
return self.__name
@property
def size(self):
return self.__size
def print_list(self, path=''):
""" retrun path and file name."""
print(path + '/' + str(self))
class Directory(Componet):
def __init__(self, name):
self.__name = name
self.__children = {} # ファイルやディレクトリを入れていく
self._parent = None
@property
def name(self):
return self.__name
@property
def size(self):
file_size = 0
for child in self.__children:
file_size += self.__children[child].size
return file_size
def add_child(self, child):
self.__children[child.name] = child
child.parent = self
def remove_child(self, child):
if child.name in self.__children:
del self.__children[child.name]
child.parent = None
def print_list(self, path=''):
print(path + '/' + str(self))
for child in self.__children:
self.__children[child].print_list(
path + '/' + self.name
)
if __name__ == '__main__':
file1 = File('temp1.txt', 1000)
file2 = File('temp2.txt', 2000)
file3 = File('temp3.txt', 3000)
file4 = File('temp4.txt', 4000)
root_dir = Directory('root')
home_dir = Directory('home')
sys_dir = Directory('sys')
taro_dir = Directory('taro')
root_dir.add_child(home_dir)
root_dir.add_child(sys_dir)
root_dir.print_list()
print('-'*50)
home_dir.add_child(taro_dir)
taro_dir.add_child(file1)
taro_dir.add_child(file2)
home_dir.add_child(file3)
sys_dir.add_child(file4)
root_dir.print_list()
print('-'*50)
sys_dir.remove_child(file4)
root_dir.print_list()