|
|
|
|
'''
|
|
|
|
|
访问者模式(Visitor Pattern):
|
|
|
|
|
表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
|
|
|
|
|
|
|
|
|
|
访问者模式(Visitor Pattern)可以用于将操作逻辑从对象结构中分离出来。假设我们有一个书城系统,其中包含不同类型的书籍(如小说、教材等),我们想要对不同类型的书籍执行不同的操作(如打印价格、增加库存等)。访问者模式允许我们定义一个新的操作而无需改变书籍的类结构。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
# 书籍类,作为元素(Element)角色
|
|
|
|
|
class Book:
|
|
|
|
|
def __init__(self, title, price, category):
|
|
|
|
|
self.title = title
|
|
|
|
|
self.price = price
|
|
|
|
|
self.category = category
|
|
|
|
|
|
|
|
|
|
def accept(self, visitor):
|
|
|
|
|
visitor.visit(self)
|
|
|
|
|
|
|
|
|
|
# 小说类,继承自书籍类
|
|
|
|
|
class NovelBook(Book):
|
|
|
|
|
def __init__(self, title, price):
|
|
|
|
|
super().__init__(title, price, "Novel")
|
|
|
|
|
|
|
|
|
|
# 教材类,继承自书籍类
|
|
|
|
|
class Textbook(Book):
|
|
|
|
|
def __init__(self, title, price):
|
|
|
|
|
super().__init__(title, price, "Textbook")
|
|
|
|
|
|
|
|
|
|
# 访问者接口
|
|
|
|
|
class IVisitor:
|
|
|
|
|
def visit(self, book):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# 具体的访问者类,实现访问者接口
|
|
|
|
|
class PricePrinter(IVisitor):
|
|
|
|
|
def visit(self, book):
|
|
|
|
|
print(f"Price of '{book.title}': ${book.price}")
|
|
|
|
|
|
|
|
|
|
class StockAdder(IVisitor):
|
|
|
|
|
def __init__(self, additional_stock):
|
|
|
|
|
self.additional_stock = additional_stock
|
|
|
|
|
|
|
|
|
|
def visit(self, book):
|
|
|
|
|
# 假设这里有一个增加库存的方法,实际上应该通过数据库或其他方式更新
|
|
|
|
|
print(f"Adding {self.additional_stock} copies of '{book.title}' to stock")
|
|
|
|
|
|
|
|
|
|
# 客户端代码
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
# 创建书籍对象
|
|
|
|
|
novel = NovelBook("The Great Gatsby", 19.99)
|
|
|
|
|
textbook = Textbook("Introduction to Algorithms", 49.99)
|
|
|
|
|
|
|
|
|
|
# 创建访问者对象
|
|
|
|
|
price_printer = PricePrinter()
|
|
|
|
|
stock_adder = StockAdder(5)
|
|
|
|
|
|
|
|
|
|
# 书籍接受访问者
|
|
|
|
|
novel.accept(price_printer)
|
|
|
|
|
textbook.accept(price_printer)
|
|
|
|
|
|
|
|
|
|
# 增加库存操作
|
|
|
|
|
novel.accept(stock_adder)
|
|
|
|
|
textbook.accept(stock_adder)
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
在这个示例中,Book 类是元素角色,它包含一个 accept 方法,该方法接受一个访问者对象。NovelBook 和 Textbook 是具体元素,它们继承自 Book 类。IVisitor 是访问者接口,声明了一个 visit 方法。PricePrinter 和 StockAdder 是实现了 IVisitor 接口的具体访问者类,它们分别用于打印书籍价格和增加书籍库存。
|
|
|
|
|
|
|
|
|
|
客户端代码创建了书籍对象和访问者对象,并通过调用书籍的 accept 方法来接受访问者的访问。这样,访问者就可以对书籍执行相应的操作。
|
|
|
|
|
|
|
|
|
|
需要注意的是,访问者模式的一个主要缺点是增加新的操作意味着增加新的访问者类,这可能会导致类的数量增加。此外,如果需要在访问者中访问对象结构的复杂关系,代码可能会变得难以理解和维护。因此,在使用访问者模式时需要权衡其优缺点。
|
|
|
|
|
'''
|