Composite Pattern

import abc
class IMenu(abc.ABC):
def __init__(self, title):
self.text = title

def traverse(self, prefix):
print(f"{prefix} {self.text}")
if hasattr(self, "components"):
for menu in self.components:
menu.traverse(prefix + prefix)

class Menu(IMenu):
def __init__(self, title):
super().__init__(title)
self.components = list()

def add(self, menu):
self.components.append(menu)

class MenuItem(IMenu):
def __init__(self, title):
super().__init__(title)

class FileMenuItem(MenuItem):
def __init__(self, title, file):
super().__init__(title)
self.file = file
getattr(file, title)()



class File:
def __init__(self, fn):
self.filename = fn
def open(self):
print(f"open {self.filename}")
def save(self):
print(f"save {self.filename}")
def close(self):
print(f"close {self.filename}")




mainMenu = Menu("file")
pyMenu = Menu('python file')
pf = File("python.py")
pyMenu.add(FileMenuItem("open", pf))
pyMenu.add(FileMenuItem("save", pf))
pyMenu.add(FileMenuItem("close", pf))

pdfMenu = Menu('pdf file')
pdf = File("README.pdf")
pdfMenu.add(FileMenuItem("open", pdf))
pdfMenu.add(FileMenuItem("save", pdf))
pdfMenu.add(FileMenuItem("close", pdf))

mainMenu.add(pyMenu)
mainMenu.add(pdfMenu)
mainMenu.add(MenuItem("exit"))
mainMenu.traverse("-")


open python.py
save python.py
close python.py
open README.pdf
save README.pdf
close README.pdf
- file
-- python file
---- open
---- save
---- close
-- pdf file
---- open
---- save
---- close
-- exit