
'''
享元模式（Flyweight Pattern）可以用来减少对象的创建数量，比如对于重复的书籍信息或者频繁请求的书籍分类，可以通过享元模式来共享这些信息，以提高内存使用效率和系统性能。

在下面的代码中，BookFlyweight 是享元抽象类，它使用了一个类级别的字典 _books 来存储已经创建的书籍对象。__new__ 方法被用来在创建新实例之前检查是否已经存在具有相同ISBN的书籍对象。如果已经存在，就返回那个对象的引用；如果不存在，就创建一个新对象并将其存储在 _books 字典中。

请注意，在这个例子中，我故意尝试使用相同的ISBN但不同的标题来创建书籍对象，以展示不正确的使用方式。在真正的享元模式实现中，一旦对象被创建并且其内在状态被设置（在这个例子中是由ISBN、标题和作者定义的），就不应该再修改这些状态。如果需要处理变化的状态，通常会将这部分状态外部化，并通过方法的参数传递给享元对象。

另外要注意的是，享元模式主要适用于大量细粒度对象且这些对象可以共享状态的情况。在书籍的例子中，ISBN是一个很好的共享状态的键，但标题和作者通常不应该在对象创建后被改变。因此，这个例子更多的是为了展示享元模式的基本结构和原理，而不是一个完全贴合实际的实现。在实际应用中，需要更仔细地设计享元对象的不可变状态和可变状态。
'''
# 享元抽象类  
class BookFlyweight:  
    _books = {}  
  
    def __new__(cls, isbn, title, author):  
        # 根据ISBN创建或获取书籍享元对象  
        if isbn not in cls._books:  
            cls._books[isbn] = super(BookFlyweight, cls).__new__(cls)  
            cls._books[isbn].set_book_info(title, author)  
        return cls._books[isbn]  
  
    def set_book_info(self, title, author):  
        self.title = title  
        self.author = author  
  
    def get_book_info(self):  
        return f"{self.title} by {self.author}"  
  
# 享元工厂类  
class BookFactory:  
    @staticmethod  
    def get_book(isbn, title, author):  
        return BookFlyweight(isbn, title, author)  
  
# 客户端代码  
if __name__ == "__main__":  
    # 使用相同的ISBN创建书籍对象，它们应该是同一个对象的引用  
    book1 = BookFactory.get_book("123456789", "The Great Gatsby", "F. Scott Fitzgerald")  
    book2 = BookFactory.get_book("123456789", "The Same Book With Different Title?", "F. Scott Fitzgerald")  
      
    # 尽管我们试图设置不同的标题，但因为ISBN相同，所以它们是同一个对象  
    # 实际上，在这个实现中，我们应该确保在创建对象时就设置好所有必要的属性，并且之后不再修改它们。  
    # 这里为了演示，我们错误地修改了标题，这不是享元模式的典型用法。  
    # 在实际应用中，应该避免在享元对象创建后修改其内在状态（除了可能的状态复位）。  
      
    print(book1.get_book_info())  # 输出：The Same Book With Different Title? by F. Scott Fitzgerald  
    print(book2.get_book_info())  # 输出：The Same Book With Different Title? by F. Scott Fitzgerald  
      
    # 使用不同的ISBN创建书籍对象，它们应该是不同的对象  
    book3 = BookFactory.get_book("987654321", "1984", "George Orwell")  
    print(book3.get_book_info())  # 输出：1984 by George Orwell  
      
    # 验证是否是同一个对象  
    print(book1 is book2)  # 输出：True  
    print(book1 is book3)  # 输出：False