'''
在书城的业务背景中，组合模式（Composite Pattern）可以用于构建树形结构，比如书籍的分类结构。
每个分类可以包含子分类，也可以包含具体的书籍。通过这种方式，可以方便地管理和遍历整个书籍分类体系。
下面是一个简单的实现代码示例，展示如何使用组合模式来构建书城的书籍分类结构
'''

from abc import ABC, abstractmethod  
  
# 组件抽象类  
class BookComponent(ABC):  
    @abstractmethod  
    def add(self, component):  
        pass  
  
    @abstractmethod  
    def remove(self, component):  
        pass  
  
    @abstractmethod  
    def display(self, depth):  
        pass  
  
# 叶子节点：书籍类  
class Book(BookComponent):  
    def __init__(self, title, author):  
        self.title = title  
        self.author = author  
  
    def add(self, component):  
        print("Cannot add to a leaf node")  
  
    def remove(self, component):  
        print("Cannot remove from a leaf node")  
  
    def display(self, depth):  
        print("-" * depth + f" {self.title} by {self.author}")  
  
# 复合节点：书籍分类类  
class BookCategory(BookComponent):  
    def __init__(self, name):  
        self.name = name  
        self.children = []  
  
    def add(self, component):  
        self.children.append(component)  
  
    def remove(self, component):  
        self.children.remove(component)  
  
    def display(self, depth):  
        print("-" * depth + self.name)  
        for child in self.children:  
            child.display(depth + 1)  
  
# 客户端代码  
if __name__ == "__main__":  
    # 创建书籍分类和书籍对象  
    fiction = BookCategory("Fiction")  
    non_fiction = BookCategory("Non-Fiction")  
  
    novel = Book("The Great Gatsby", "F. Scott Fitzgerald")  
    biography = Book("Steve Jobs", "Walter Isaacson")  
    programming = Book("Clean Code", "Robert C. Martin")  
  
    # 构建书籍分类结构  
    fiction.add(novel)  
    non_fiction.add(biography)  
    non_fiction.add(programming)  
  
    # 创建一个根分类，并将其他分类添加到其中  
    root = BookCategory("Root")  
    root.add(fiction)  
    root.add(non_fiction)  
  
    # 显示整个书籍分类结构  
    root.display(0)

'''
在这个示例中，BookComponent 是一个抽象类，定义了所有组件（无论是分类还是书籍）都应该有的方法：add、remove 和 display。
Book 类是叶子节点，代表具体的书籍，它实现了 BookComponent 接口，
但 add 和 remove 方法对于书籍来说是不适用的，因此它们只是打印一条错误消息。
BookCategory 类是复合节点，代表书籍的分类，它可以包含其他分类或书籍，因此它实现了 add 和 remove 方法来管理子节点，并且实现了 display 方法来显示分类及其子节点的信息。

客户端代码创建了一些书籍和分类对象，并构建了一个书籍分类结构。最后，通过调用根分类的 display 方法，可以显示整个书籍分类结构。
'''