diff --git a/异常/1 软件不能挂掉/tf-21.py b/基本结构/异常/1 软件不能挂掉/tf-21.py similarity index 100% rename from 异常/1 软件不能挂掉/tf-21.py rename to 基本结构/异常/1 软件不能挂掉/tf-21.py diff --git a/异常/2 时间停止在那一刻/tf-22.py b/基本结构/异常/2 时间停止在那一刻/tf-22.py similarity index 100% rename from 异常/2 时间停止在那一刻/tf-22.py rename to 基本结构/异常/2 时间停止在那一刻/tf-22.py diff --git a/异常/3 所有错误的应对/tf-23.py b/基本结构/异常/3 所有错误的应对/tf-23.py similarity index 100% rename from 异常/3 所有错误的应对/tf-23.py rename to 基本结构/异常/3 所有错误的应对/tf-23.py diff --git a/对象设计模式/readme.md b/对象设计模式/readme.md new file mode 100644 index 0000000..d50a00b --- /dev/null +++ b/对象设计模式/readme.md @@ -0,0 +1,22 @@ + + +# 目标 +本节使用一个书城的各种业务环节来展示面向对象的各种设计模式 。 + +# 任务 +背景假设为一个综合书城,提供线上线下购买,还经营一个书吧、一个报告厅 + +# 说明 +因为 Python 对象协议的机制,多态、接口概念发生了根本变化。 +很多模式中,类的继承关系没必要了。下面示例中很多依旧保持了基类 +一是致敬经典,二是起到一个工程上更工整强注释的作用 + +另外,Python的动态语言的特性 。使得一些C++、Java 的模式没用了。 +比如 “ 原型模式(Prototype)” ,可以使用copy.deepcopy()非常简便来创建。 + +面向对象设计模式是软件工程中一组经过验证的、可重复使用的解决方案, +用于解决在设计和实现面向对象系统时经常遇到的设计问题。 +面向对象的模式把编程过程中的一些思路套路固定化,并给一个名字方便理解 。 +所以,模式不是语法,而是编程思路。 +那为啥,面向过程没有这么做? +是因为这个思维提炼过程,充分利用了面向对象语言的特性:封装、继承、多态。 \ No newline at end of file diff --git a/对象设计模式/创建型/010 单例.py b/对象设计模式/创建型/010 单例.py new file mode 100644 index 0000000..41b1f03 --- /dev/null +++ b/对象设计模式/创建型/010 单例.py @@ -0,0 +1,17 @@ +''' +全局只允许一个实例的办法, +在该电商系统中,全局只有一个数据库连接,使用单例模式确保在整个应用程序内只创建一次数据库连接实例。 +''' + +class DatabaseConnection: + _instance = None + + def __new__(cls): + if not cls._instance: + cls._instance = super().__new__(cls) + cls._instance.connect_to_db() + return cls._instance + + def connect_to_db(self): + # 连接到数据库的代码... + pass \ No newline at end of file diff --git a/对象设计模式/创建型/020 工厂.py b/对象设计模式/创建型/020 工厂.py new file mode 100644 index 0000000..b6aef48 --- /dev/null +++ b/对象设计模式/创建型/020 工厂.py @@ -0,0 +1,31 @@ +# 如果有一个选择结构来决定实现不同的类,再面向对象设计里面一般把这个选择做成一个类,叫做工厂模式 +# 定义一个ProductFactory类,用于创建不同类型的商品实例(如电子产品、书籍等)。具体的产品由子类实现。 +# + +class Product: + def __init__(self, name, price): + self.name = name + self.price = price + +class Electronic(Product): + def __init__(self, name, price, brand): + super().__init__(name, price) + self.brand = brand + +class Book(Product): + def __init__(self, name, price, author): + super().__init__(name, price) + self.author = author + +class ProductFactory: + @staticmethod + def create_product(product_type, *args, **kwargs): + if product_type == 'electronic': + return Electronic(*args, **kwargs) + elif product_type == 'book': + return Book(*args, **kwargs) + else: + raise ValueError("Invalid product type") + +# 使用工厂方法创建产品 +product = ProductFactory.create_product('book', 'Python编程艺术', 50.0, 'Mark Lutz') \ No newline at end of file diff --git a/对象设计模式/创建型/070 建造者.py b/对象设计模式/创建型/070 建造者.py new file mode 100644 index 0000000..4fab22a --- /dev/null +++ b/对象设计模式/创建型/070 建造者.py @@ -0,0 +1,114 @@ +''' +建造者模式(Builder Pattern)允许构建一个复杂对象的各个部分,然后一步一步地返回这个对象的完整版本。 +将建造者模式应用于网购的下单和出库过程时,我们可以设计一个Order类来表示订单, +以及一个OrderBuilder类来构建订单的各个部分。 +此外,我们还可以引入一个ShoppingCart类来表示购物车,以及一个Inventory类来处理库存和出库逻辑。 +''' + +###################################################################### +# Order类,它包含订单的基本信息,如下单时间、用户信息、订单项列表 +###################################################################### +from datetime import datetime + +class OrderItem: + def __init__(self, product_id, quantity): + self.product_id = product_id + self.quantity = quantity + +class Order: + def __init__(self, user_id, order_items, order_time=None): + self.user_id = user_id + self.order_items = order_items + self.order_time = order_time or datetime.now() + self.status = "PLACED" # 初始状态为已下单 + + def __str__(self): + return f"Order for user {self.user_id} placed at {self.order_time}. Status: {self.status}" + + def fulfill(self, inventory): + # 出库逻辑,这里简化处理 + for item in self.order_items: + if not inventory.deduct_stock(item.product_id, item.quantity): + return False + self.status = "FULFILLED" + return True + +###################################################################### +# OrderBuilder类,用于构建订单 +###################################################################### +class OrderBuilder: + def __init__(self): + self.reset() + + def reset(self): + self._user_id = None + self._order_items = [] + + def for_user(self, user_id): + self._user_id = user_id + return self + + def add_item(self, product_id, quantity): + self._order_items.append(OrderItem(product_id, quantity)) + return self + + def build(self): + if not self._user_id or not self._order_items: + raise ValueError("Order cannot be built without user and items.") + return Order(self._user_id, self._order_items) + + +###################################################################### +# 购物车和库存类 +###################################################################### +class ShoppingCart: + def __init__(self, user_id): + self.user_id = user_id + self.items = {} # {product_id: quantity} + + def add_to_cart(self, product_id, quantity): + self.items[product_id] = self.items.get(product_id, 0) + quantity + + def checkout(self): + order_items = [OrderItem(product_id, quantity) for product_id, quantity in self.items.items()] + self.items.clear() # 清空购物车 + return order_items + +class Inventory: + def __init__(self): + self.stock = {} # {product_id: quantity} + + def add_stock(self, product_id, quantity): + self.stock[product_id] = self.stock.get(product_id, 0) + quantity + + def deduct_stock(self, product_id, quantity): + if self.stock.get(product_id, 0) >= quantity: + self.stock[product_id] -= quantity + return True + return False + +###################################################################### +# 模拟整个下单和出库过程 +###################################################################### +# 初始化库存和购物车 +inventory = Inventory() +inventory.add_stock("book1", 10) +inventory.add_stock("book2", 5) + +cart = ShoppingCart(user_id="user123") +cart.add_to_cart("book1", 2) +cart.add_to_cart("book2", 1) + +# 使用OrderBuilder构建订单 +order_items = cart.checkout() # 结账,获取订单项列表并清空购物车 +order_builder = OrderBuilder().for_user("user123") +for item in order_items: + order_builder.add_item(item.product_id, item.quantity) +order = order_builder.build() # 构建订单对象 +print(order) # 输出订单信息 + +# 出库处理 +if order.fulfill(inventory): + print("Order has been fulfilled.") +else: + print("Order fulfillment failed due to insufficient stock.") \ No newline at end of file diff --git a/对象设计模式/创建型/180 享元.py b/对象设计模式/创建型/180 享元.py new file mode 100644 index 0000000..c86e477 --- /dev/null +++ b/对象设计模式/创建型/180 享元.py @@ -0,0 +1,55 @@ + +''' +享元模式(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 \ No newline at end of file diff --git a/对象设计模式/结构型/050 装饰器.py b/对象设计模式/结构型/050 装饰器.py new file mode 100644 index 0000000..ec09e50 --- /dev/null +++ b/对象设计模式/结构型/050 装饰器.py @@ -0,0 +1,23 @@ +# 装饰器模式允许我们在不修改原有类的基础上,动态地添加额外的功能。 +# 就增加功能来说,装饰器模式比生成子类更为灵活。 +# 餐吧的顾客可以选择为他们的咖啡添加额外的调料。 +class Beverage: + def __init__(self, description): + self.description = description + self.price = 0.0 + + def cost(self): + return self.price + +class CondimentDecorator(Beverage): # 进行装饰 + def __init__(self, beverage, description, price_increase): + self.beverage = beverage + self.description = f"{beverage.description}, {description}" + self.price_increase = price_increase + + def cost(self): + return self.beverage.cost() + self.price_increase + +# 使用装饰器模式 +coffee = Beverage("Espresso") +coffee_with_chocolate = CondimentDecorator(coffee, "Chocolate", 0.50) \ No newline at end of file diff --git a/对象设计模式/结构型/080 适配器.py b/对象设计模式/结构型/080 适配器.py new file mode 100644 index 0000000..d75a74a --- /dev/null +++ b/对象设计模式/结构型/080 适配器.py @@ -0,0 +1,42 @@ +''' +适配器模式(Adapter) +应用:将一个类的接口转换成客户期望的另一个接口,使得原本由于接口不兼容而无法一起工作的类能够一起工作。 +''' + +######################################################################## +# 定义一个目标接口Target和一个与之不兼容的类Adaptee +############################################################################ +# 目标接口 +class Target: + def request(self): + pass + +# 需要适配的类 +class Adaptee: + def specific_request(self): + print("Called Adaptee's specific_request.") + +######################################################################## +# 定义一个适配器类Adapter,它实现了Target接口,并且持有Adaptee的实例, +# 从而能够在request方法中调用Adaptee的specific_request方法 +# 一个继承,一个当参数加入构造函数 +############################################################################ +# 适配器 +class Adapter(Target): + def __init__(self, adaptee): + self.adaptee = adaptee + + def request(self): + # 调用Adaptee的specific_request方法 + self.adaptee.specific_request() + + +if __name__ == "__main__": + # 创建Adaptee实例 + adaptee = Adaptee() + + # 创建Adapter实例,将Adaptee实例作为参数传递 + adapter = Adapter(adaptee) + + # 客户端调用Target的request方法,实际上调用的是Adaptee的specific_request方法 + adapter.request() \ No newline at end of file diff --git a/对象设计模式/结构型/140 代理.py b/对象设计模式/结构型/140 代理.py new file mode 100644 index 0000000..66fc5ee --- /dev/null +++ b/对象设计模式/结构型/140 代理.py @@ -0,0 +1,60 @@ +''' +代理模式(Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问。 +在书城的业务背景中,代理模式(Proxy Pattern)可以应用于多种场景,例如实现延迟加载、访问控制、远程代理等。 +下面示例展示如何使用代理模式来控制对书城中书籍对象的访问。 +假设我们有一个Book类,代表书城中的书籍,和一个BookProxy类,作为Book的代理类,来控制对书籍的访问。 +''' + +# 书籍类 +class Book: + def __init__(self, title, author, price): + self.title = title + self.author = author + self.price = price + self.is_loaded = False # 假设书籍内容初始时是未加载的 + + def load_content(self): + # 模拟加载书籍内容的过程,这里仅打印一条消息 + print(f"Loading content for book '{self.title}' by {self.author}...") + self.is_loaded = True + + def display(self): + if not self.is_loaded: + self.load_content() + print(f"Book Title: {self.title}") + print(f"Author: {self.author}") + print(f"Price: {self.price}") + print("Content is loaded and displayed.") + +# 书籍代理类 +class BookProxy: + def __init__(self, book): + self.book = book + + def display(self): + # 在显示书籍信息之前,代理可以控制一些额外的操作 + # 比如检查用户权限、记录访问日志等 + # 这里我们模拟一个简单的访问控制 + print("Checking access permissions...") + # 假设权限检查通过,调用实际对象的display方法 + self.book.display() + +# 客户端代码 +if __name__ == "__main__": + # 创建一个书籍对象(假设内容尚未加载) + book = Book("The Great Gatsby", "F. Scott Fitzgerald", 29.99) + # 创建一个书籍代理对象 + book_proxy = BookProxy(book) + # 通过代理来访问书籍信息 + book_proxy.display() + + +''' +在这个示例中,Book类有一个load_content方法来模拟加载书籍内容的过程,以及一个display方法来显示书籍的信息。 +在实际应用中,load_content可能会执行更加复杂的操作,如从数据库或远程服务器加载数据。 +BookProxy类作为代理,包装了对Book对象的访问。 +在这个简单的例子中,它在调用display方法之前执行了一个模拟的权限检查。 +在实际应用中,代理类可以执行各种操作,如缓存、懒加载、权限验证等。 +客户端代码通过创建BookProxy对象来间接访问Book对象,而不是直接访问。 +这种方式提供了一种灵活的控制机制,使得可以在不修改原始类的情况下增加额外的功能或控制逻辑。 +''' \ No newline at end of file diff --git a/对象设计模式/结构型/150 外观.py b/对象设计模式/结构型/150 外观.py new file mode 100644 index 0000000..98a5de9 --- /dev/null +++ b/对象设计模式/结构型/150 外观.py @@ -0,0 +1,75 @@ +''' +在书城的业务背景中,外观模式(Facade Pattern)可以用于提供一个简化的接口,以隐藏系统的复杂性。 +假设书城提供了多种服务,如用户认证、购物车管理、订单处理等,外观模式可以将这些服务整合到一个统一的接口中, +使客户端能够更方便地使用这些服务。 +下面是一个简单的实现代码示例,展示如何使用外观模式来整合书城的不同服务: +''' + +# 用户服务类 +class UserService: + def authenticate(self, username, password): + # 这里是用户认证的实现代码 + print(f"Authenticating user {username}...") + return True # 假设认证总是成功 + +# 购物车服务类 +class CartService: + def add_to_cart(self, user_id, book_id): + # 这里是将书籍添加到购物车的实现代码 + print(f"User {user_id} added book {book_id} to the cart.") + + def remove_from_cart(self, user_id, book_id): + # 这里是从购物车中移除书籍的实现代码 + print(f"User {user_id} removed book {book_id} from the cart.") + +# 订单服务类 +class OrderService: + def create_order(self, user_id, cart_items): + # 这里是创建订单的实现代码 + print(f"Creating order for user {user_id} with items {cart_items}...") + return "OrderID123" # 假设返回一个订单ID + +# 书城外观类 +class BookstoreFacade: + def __init__(self): + self.user_service = UserService() + self.cart_service = CartService() + self.order_service = OrderService() + + def login_and_add_to_cart(self, username, password, book_id): + if self.user_service.authenticate(username, password): + print("Login successful.") + # 假设用户ID为1(实际应用中应该通过认证服务获取) + user_id = 1 + self.cart_service.add_to_cart(user_id, book_id) + else: + print("Login failed.") + + def checkout(self, username, password): + if self.user_service.authenticate(username, password): + print("Login successful.") + # 假设用户ID为1(实际应用中应该通过认证服务获取) + user_id = 1 + # 假设获取购物车项目的方法存在(实际应用中需要实现) + cart_items = self.get_cart_items(user_id) + if cart_items: + order_id = self.order_service.create_order(user_id, cart_items) + print(f"Order created with ID: {order_id}") + else: + print("Your cart is empty.") + else: + print("Login failed.") + + def get_cart_items(self, user_id): + # 这里应该有一个方法来获取购物车中的项目,但为了简化示例,我们直接返回一个列表 + return [1, 2, 3] # 假设的书籍ID列表 + +# 客户端代码 +if __name__ == "__main__": + bookstore = BookstoreFacade() + + # 用户登录并添加书籍到购物车 + bookstore.login_and_add_to_cart("alice", "password123", "book456") + + # 用户结账创建订单 + bookstore.checkout("alice", "password123") \ No newline at end of file diff --git a/对象设计模式/结构型/160 组合.py b/对象设计模式/结构型/160 组合.py new file mode 100644 index 0000000..13f9d7f --- /dev/null +++ b/对象设计模式/结构型/160 组合.py @@ -0,0 +1,85 @@ +''' +在书城的业务背景中,组合模式(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 方法,可以显示整个书籍分类结构。 +''' \ No newline at end of file diff --git a/对象设计模式/结构型/170 桥接.py b/对象设计模式/结构型/170 桥接.py new file mode 100644 index 0000000..3ab3a0f --- /dev/null +++ b/对象设计模式/结构型/170 桥接.py @@ -0,0 +1,92 @@ +''' +桥接模式(Bridge Pattern)可以将抽象与实现解耦,让它们可以独立变化。 +这在处理多种分类的书籍时特别有用,比如你想在不同的平台上展示这些书籍,同时这些书籍还分属不同的分类。 +下面是一个简单的实现代码示例,展示如何使用桥接模式来构建书城的书籍分类与展示平台: +''' + +# 定义书籍接口 +class IBook: + def get_title(self): + pass + + def get_author(self): + pass + +# 具体书籍实现 +class NovelBook(IBook): + def __init__(self, title, author): + self.title = title + self.author = author + + def get_title(self): + return self.title + + def get_author(self): + return self.author + +# 定义抽象分类 +class BookCategory: + def __init__(self, name): + self.name = name + self.books = [] + + def add_book(self, book): + self.books.append(book) + + def get_books(self): + return self.books + +# 定义抽象展示平台 +class DisplayPlatform: + def display(self, book): + pass + +# 具体展示平台实现 +class WebDisplayPlatform(DisplayPlatform): + def display(self, book): + return f"On the web: {book.get_title()} by {book.get_author()}" + +class MobileDisplayPlatform(DisplayPlatform): + def display(self, book): + return f"On mobile: {book.get_title()} by {book.get_author()}" + +# 桥接类,将分类与展示平台连接起来 +class BookShop: + def __init__(self, category, platform): + self.category = category + self.platform = platform + + def show_books(self): + for book in self.category.get_books(): + print(self.platform.display(book)) + +# 客户端代码 +if __name__ == "__main__": + # 创建书籍 + novel1 = NovelBook("The Great Gatsby", "F. Scott Fitzgerald") + novel2 = NovelBook("1984", "George Orwell") + + # 创建分类 + fiction_category = BookCategory("Fiction") + fiction_category.add_book(novel1) + fiction_category.add_book(novel2) + + # 创建展示平台 + web_platform = WebDisplayPlatform() + mobile_platform = MobileDisplayPlatform() + + # 创建书城并展示书籍 + web_bookshop = BookShop(fiction_category, web_platform) + web_bookshop.show_books() + + mobile_bookshop = BookShop(fiction_category, mobile_platform) + mobile_bookshop.show_books() + + +''' +在这个示例中,IBook 是一个接口,定义了书籍应有的行为(比如获取标题和作者)。NovelBook 是一个具体书籍类,实现了 IBook 接口。BookCategory 是一个书籍分类类,它可以包含多个书籍实例。 + +DisplayPlatform 是一个抽象展示平台类,定义了如何展示书籍。WebDisplayPlatform 和 MobileDisplayPlatform 是具体展示平台类,分别实现了 DisplayPlatform 接口,以提供不同的展示方式。 + +BookShop 是一个桥接类,它将书籍分类与展示平台连接起来,通过 show_books 方法可以展示分类中的所有书籍。 +''' \ No newline at end of file diff --git a/对象设计模式/行为型/030 策略.py b/对象设计模式/行为型/030 策略.py new file mode 100644 index 0000000..cff9760 --- /dev/null +++ b/对象设计模式/行为型/030 策略.py @@ -0,0 +1,66 @@ +# 和工厂模式类似,不过这里的结果只是产生不同的类方法 +# 设想书店有多种折扣策略,比如“普通会员折扣”、“金牌会员折扣”和“无折扣”。每种折扣策略都是一个具体的策略实现。 + +from abc import ABC, abstractmethod + +######################################################## +# 创建折扣策略接口 +######################################################## +class DiscountStrategy(ABC): + @abstractmethod + def calculate_discount(self, book_price): + pass + +######################################################## +# 创建实现了DiscountStrategy接口的具体折扣策略类 +######################################################## +class NoDiscountStrategy(DiscountStrategy): + def calculate_discount(self, book_price): + return book_price # 无折扣,原价返回 + +class RegularMemberDiscountStrategy(DiscountStrategy): + def calculate_discount(self, book_price): + return book_price * 0.9 # 普通会员9折 + +class GoldMemberDiscountStrategy(DiscountStrategy): + def calculate_discount(self, book_price): + return book_price * 0.8 # 金牌会员8折 + +######################################################## +# 定义Book类和Bookstore类。Book类包含书籍的信息和价格,Bookstore类则使用折扣策略来计算书籍的折后价 +######################################################## +class Book: + def __init__(self, title, price): + self.title = title + self.price = price + +class Bookstore: + def __init__(self, discount_strategy): + self.discount_strategy = discount_strategy + + def set_discount_strategy(self, discount_strategy): + self.discount_strategy = discount_strategy + + def calculate_final_price(self, book): + discounted_price = self.discount_strategy.calculate_discount(book.price) + return discounted_price + + +if __name__ == "__main__": + # 创建书籍对象 + book = Book("The Great Gatsby", 30.0) + + # 创建折扣策略对象 + no_discount = NoDiscountStrategy() + regular_discount = RegularMemberDiscountStrategy() + gold_discount = GoldMemberDiscountStrategy() + + # 创建书店对象,并设置不同的折扣策略 + bookstore = Bookstore(no_discount) + print(f"No Discount: The final price of '{book.title}' is {bookstore.calculate_final_price(book)}") + + bookstore.set_discount_strategy(regular_discount) + print(f"Regular Member Discount: The final price of '{book.title}' is {bookstore.calculate_final_price(book)}") + + bookstore.set_discount_strategy(gold_discount) + print(f"Gold Member Discount: The final price of '{book.title}' is {bookstore.calculate_final_price(book)}") \ No newline at end of file diff --git a/对象设计模式/行为型/040 观察者.py b/对象设计模式/行为型/040 观察者.py new file mode 100644 index 0000000..fda3eec --- /dev/null +++ b/对象设计模式/行为型/040 观察者.py @@ -0,0 +1,45 @@ +# 观察者模式允许一个对象(观察者)监听另一个对象(主题)的状态变化,并在状态变化时得到通知。 +# 主类信息发生变化,通知登记的各个对象(把自己当当参数传过去)自行处理变化 +# 当购物车中的商品数量发生变化时,库存系统和价格计算系统需要实时更新。 +# 观察者模式(Observer)或发布-订阅模式(Publish-Subscribe) + +import abc + +class Observer(metaclass=abc.ABCMeta): + @abc.abstractmethod + def update(self, cart): + pass + +class InventorySystem(Observer): + def update(self, cart): + # 更新库存逻辑... + pass + +class PriceCalculator(Observer): + def update(self, cart): + # 重新计算总价逻辑... + pass + +class ShoppingCart: + def __init__(self): + self._items = {} + self.observers = [] + + def add_item(self, item_id, quantity): + # 添加商品到购物车并通知所有观察者 + self._items[item_id] = quantity + for observer in self.observers: + observer.update(self) + + def attach(self, observer): + self.observers.append(observer) + +# 创建购物车并添加观察者 +cart = ShoppingCart() +inventory_system = InventorySystem() +price_calculator = PriceCalculator() + +cart.attach(inventory_system) +cart.attach(price_calculator) + +cart.add_item('item1', 2) # 当添加商品时,库存系统和价格计算器都会收到更新通知 \ No newline at end of file diff --git a/对象设计模式/行为型/060 状态.py b/对象设计模式/行为型/060 状态.py new file mode 100644 index 0000000..65791cd --- /dev/null +++ b/对象设计模式/行为型/060 状态.py @@ -0,0 +1,80 @@ +''' +状态模式(State Pattern)允许一个对象在其内部状态改变时改变它的行为。 +这个模式将状态封装成独立的类,并将状态转换的逻辑分散到这些类中,从而减少相互间的依赖。 +以下是一个使用状态模式的简单示例,我们将创建一个订单类Order,它有几个状态: +Placed(已下单)、Paid(已支付)、Fulfilled(已履行)和Delivered(已交付)。 +每个状态都是一个类,它们继承自一个抽象状态类OrderState。 +''' +################################################################################ +# 定义抽象状态类和一些具体的状态类 +################################################################################ +class OrderState: + def handle(self, order): + pass + +class PlacedState(OrderState): + def handle(self, order): + print("Order placed. Waiting for payment...") + order.set_state(order.get_paid_state()) + +class PaidState(OrderState): + def handle(self, order): + print("Order paid. Preparing for fulfillment...") + order.set_state(order.get_fulfilled_state()) + +class FulfilledState(OrderState): + def handle(self, order): + print("Order fulfilled. Preparing for delivery...") + order.set_state(order.get_delivered_state()) + +class DeliveredState(OrderState): + def handle(self, order): + print("Order delivered. Process completed.") + +################################################################################ +# 定义Order类,它包含一个对当前状态的引用,并且能够通过set_state方法改变其状态 +################################################################################ +class Order: + def __init__(self): + self._state = None + self.set_state(self.get_placed_state()) + + def set_state(self, state): + self._state = state + + def get_state(self): + return self._state + + def get_placed_state(self): + return PlacedState() + + def get_paid_state(self): + return PaidState() + + def get_fulfilled_state(self): + return FulfilledState() + + def get_delivered_state(self): + return DeliveredState() + + def process(self): + self._state.handle(self) + +################################################################################ +# 创建一个Order对象并模拟其状态转换 +################################################################################ + +if __name__ == "__main__": + order = Order() + + # 模拟订单处理流程 + order.process() # 初始状态为Placed,执行后将变为Paid + order.process() # 当前状态为Paid,执行后将变为Fulfilled + order.process() # 当前状态为Fulfilled,执行后将变为Delivered + order.process() # 当前状态为Delivered,执行后不会改变,因为Delivered是最终状态 + +################################################################################ +# 这个例子中,每个状态类都负责决定下一个状态是什么,并在handle方法中触发状态转换。 +# Order类不直接知道所有可能的状态转换,这些逻辑被封装在状态类中。 +# 这使得添加新的状态或修改现有状态的行为变得更加容易,因为不需要修改Order类本身。 +################################################################################ \ No newline at end of file diff --git a/对象设计模式/行为型/090 模板方法.py b/对象设计模式/行为型/090 模板方法.py new file mode 100644 index 0000000..728af43 --- /dev/null +++ b/对象设计模式/行为型/090 模板方法.py @@ -0,0 +1,71 @@ +''' +模板方法模式(Template Method) +定义算法的骨架,而将一些步骤延迟到子类中实现。 +''' + +from abc import ABC, abstractmethod + +class AbstractClass(ABC): + def template_method(self): + # 这是一个模板方法,它定义了一个算法的骨架 + self.base_operation1() + self.required_operations1() + self.base_operation2() + self.hook1() + self.required_operations2() + self.base_operation3() + self.hook2() + + @abstractmethod + def base_operation1(self): + pass + + @abstractmethod + def base_operation2(self): + pass + + @abstractmethod + def base_operation3(self): + pass + + @abstractmethod + def required_operations1(self): + pass + + @abstractmethod + def required_operations2(self): + pass + + def hook1(self): + pass # 钩子操作,子类可以选择是否覆盖 + + def hook2(self): + pass # 另一个钩子操作 + + +class ConcreteClass(AbstractClass): + def base_operation1(self): + print("AbstractClass says: I am doing the bulk of the work") + + def base_operation2(self): + print("AbstractClass says: But I let subclasses override some operations") + + def base_operation3(self): + print("AbstractClass says: But I am doing the bulk of the work anyway") + + def required_operations1(self): + print("ConcreteClass says: Implemented Operation1") + + def required_operations2(self): + print("ConcreteClass says: Implemented Operation2") + + def hook1(self): + print("ConcreteClass says: Overridden Hook1") + + def hook2(self): + # 没有覆盖hook2,所以它将执行AbstractClass中的空实现 + pass + +if __name__ == "__main__": + concrete_class = ConcreteClass() + concrete_class.template_method() \ No newline at end of file diff --git a/对象设计模式/行为型/110 中介者.py b/对象设计模式/行为型/110 中介者.py new file mode 100644 index 0000000..f55fca5 --- /dev/null +++ b/对象设计模式/行为型/110 中介者.py @@ -0,0 +1,86 @@ +''' +中介者模式(Mediator Pattern)是一种行为型设计模式,它定义了一个中介对象来封装一系列对象之间的交互。 +中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 + +设想书店管理系统,其中包含了多个组件,比如库存管理、订单处理、顾客管理等。 +这些组件之间需要相互通信来协同工作。我们可以使用中介者模式来减少这些组件之间的直接依赖。 + +在这个示例中,BookstoreMediator 充当了中介者的角色,它协调了库存管理、订单处理和顾客管理之间的交互。 +当某个事件发生时(比如顾客下订单),相应的组件会通过中介者发送通知,中介者再根据事件类型协调其他组件的响应。 +''' + +from abc import ABC, abstractmethod + +#定义一个中介者接口和具体的中介者实现 + +# 中介者接口 +class Mediator(ABC): + @abstractmethod + def notify(self, sender, event): + pass + +# 具体的中介者实现 +class BookstoreMediator(Mediator): + def __init__(self, inventory, order, customer): + self.inventory = inventory + self.order = order + self.customer = customer + + def notify(self, sender, event): + if event == 'book_ordered': + print("BookstoreMediator: Order notification received. Checking inventory...") + if self.inventory.has_stock(): + print("BookstoreMediator: Inventory has stock. Processing order...") + self.order.process_order() + self.customer.notify_order_success() + else: + print("BookstoreMediator: Inventory out of stock. Cancelling order...") + self.order.cancel_order() + self.customer.notify_order_failure() + # 可以添加更多的事件处理逻辑 + +# 库存管理组件 +class Inventory: + def has_stock(self): + # 这里简化逻辑,直接返回有库存 + return True + +# 订单处理组件 +class Order: + def process_order(self): + print("Order: Order is being processed...") + + def cancel_order(self): + print("Order: Order is being cancelled...") + +# 顾客管理组件 +class Customer: + def notify_order_success(self): + print("Customer: Order successful. Notifying customer...") + + def notify_order_failure(self): + print("Customer: Order failed. Notifying customer...") + +# 组件之间的交互通过中介者进行 +class BookstoreComponent: + def __init__(self, mediator): + self.mediator = mediator + + def send_notification(self, event): + self.mediator.notify(self, event) + +# 示例使用 +if __name__ == "__main__": + # 创建组件 + inventory = Inventory() + order = Order() + customer = Customer() + + # 创建中介者并注入组件 + mediator = BookstoreMediator(inventory, order, customer) + + # 创建与中介者关联的书店组件(这里以订单为例) + order_component = BookstoreComponent(mediator) + + # 触发事件(比如:下订单) + order_component.send_notification('book_ordered') \ No newline at end of file diff --git a/对象设计模式/行为型/120 责任链.py b/对象设计模式/行为型/120 责任链.py new file mode 100644 index 0000000..67ef4d0 --- /dev/null +++ b/对象设计模式/行为型/120 责任链.py @@ -0,0 +1,96 @@ +''' +职责链模式(Chain of Responsibility Pattern) + +一种行为设计模式,它允许你将请求沿着处理者链进行发送。 +收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。 + +在书城的业务背景中,可以想象有这样的场景: +客户下了一个订单,该订单需要经历多个处理步骤,比如验证库存、计算价格、生成发货通知等。 +这些处理步骤按照一定的顺序组织成一个处理链 +''' + +class Order: + def __init__(self, book_id, quantity): + self.book_id = book_id + self.quantity = quantity + + +class Handler: + def __init__(self, successor=None): + self.successor = successor + + def handle_request(self, order): + raise NotImplementedError("Subclasses must implement handle_request()") + + def successor_handle_request(self, order): + if self.successor is not None: + return self.successor.handle_request(order) + + +class InventoryHandler(Handler): + def handle_request(self, order): + if check_inventory(order.book_id, order.quantity): + print("InventoryHandler: Inventory checked, enough stock.") + return self.successor_handle_request(order) + else: + print("InventoryHandler: Inventory check failed, not enough stock.") + return False + + +class PricingHandler(Handler): + def handle_request(self, order): + price = calculate_price(order.book_id, order.quantity) + print(f"PricingHandler: Price calculated, total: {price}") + return self.successor_handle_request(order) + + +class NotificationHandler(Handler): + def handle_request(self, order): + send_notification(order) + print("NotificationHandler: Notification sent to customer.") + # Since this is the end of the chain, no successor to call. + return True + + +# Dummy functions to simulate the bookstore logic +def check_inventory(book_id, quantity): + return True # Simulate enough stock + + +def calculate_price(book_id, quantity): + return 10.0 * quantity # Simulate a fixed price per book + + +def send_notification(order): + pass # Simulate sending a notification to the customer + + +# Setting up the Chain of Responsibility +inventory_handler = InventoryHandler() +pricing_handler = PricingHandler() +notification_handler = NotificationHandler() + +inventory_handler.successor = pricing_handler +pricing_handler.successor = notification_handler + +# Client code +order = Order(book_id="12345", quantity=2) +result = inventory_handler.handle_request(order) +if result: + print("Order processing completed successfully.") +else: + print("Order processing failed.") + +''' +在这个例子中,我们有一个Handler基类,它定义了一个处理请求的基本框架。 +具体的处理逻辑则在子类InventoryHandler、PricingHandler和NotificationHandler中实现。 +这些子类形成了职责链,通过successor引用链接在一起。 + +客户下了一个订单后,这个订单请求会从库存处理器(InventoryHandler)开始处理。 +如果库存足够,请求将被传递给价格处理器(PricingHandler)来计算总价。 +然后,价格处理器再将请求传递给通知处理器(NotificationHandler), +最后发送通知给客户。 +如果任何处理器无法处理请求(例如,库存不足),处理将在那里终止,并且返回相应的结果。 + +这个模式的好处是可以很容易地改变处理的顺序或者增加/删除处理器,而不需要修改已有的代码。 +''' \ No newline at end of file diff --git a/对象设计模式/行为型/130 命令.py b/对象设计模式/行为型/130 命令.py new file mode 100644 index 0000000..c43ce42 --- /dev/null +++ b/对象设计模式/行为型/130 命令.py @@ -0,0 +1,75 @@ +''' +命令模式(Command Pattern)是一种行为设计模式,它封装了一个请求作为一个对象,从而让你使用不同的请求把客户端与服务端操作解耦。在书城的业务背景中,命令模式可以用来实现例如添加购物车项、结算订单、发送通知等操作。 + +下面是一个简单的使用Python实现的命令模式示例,以书城的购物车操作为例 +''' + +# 购物车类 +class ShoppingCart: + def __init__(self): + self.items = [] + + def add_item(self, book_id, quantity): + self.items.append({'book_id': book_id, 'quantity': quantity}) + print(f"Added {quantity} of book ID {book_id} to the cart.") + + def remove_item(self, book_id): + self.items = [item for item in self.items if item['book_id'] != book_id] + print(f"Removed book ID {book_id} from the cart.") + +# 命令接口 +class Command: + def execute(self): + pass + +# 具体命令类 - 添加购物车项 +class AddToCartCommand(Command): + def __init__(self, shopping_cart, book_id, quantity): + self.shopping_cart = shopping_cart + self.book_id = book_id + self.quantity = quantity + + def execute(self): + self.shopping_cart.add_item(self.book_id, self.quantity) + +# 具体命令类 - 移除购物车项 +class RemoveFromCartCommand(Command): + def __init__(self, shopping_cart, book_id): + self.shopping_cart = shopping_cart + self.book_id = book_id + + def execute(self): + self.shopping_cart.remove_item(self.book_id) + +# 调用者(Invoker)类 +class Invoker: + def __init__(self): + self.commands = [] + + def store_and_execute_command(self, command): + self.commands.append(command) + command.execute() + +# 客户端代码 +if __name__ == "__main__": + cart = ShoppingCart() + invoker = Invoker() + + # 创建添加购物车项命令 + add_command = AddToCartCommand(cart, "12345", 2) + invoker.store_and_execute_command(add_command) + + # 创建移除购物车项命令 + remove_command = RemoveFromCartCommand(cart, "12345") + invoker.store_and_execute_command(remove_command) + +''' +在这个例子中,我们有一个ShoppingCart类,它有两个方法:add_item和remove_item,用于添加和移除购物车项。然后,我们定义了一个命令接口Command和一个调用者Invoker。Invoker可以存储并执行命令。 + +具体命令类AddToCartCommand和RemoveFromCartCommand实现了Command接口,并在execute方法中调用了ShoppingCart的相应操作。 + +客户端代码创建了ShoppingCart实例和Invoker实例,并创建了添加和移除购物车项的具体命令对象。这些命令对象通过调用者的store_and_execute_command方法被存储和执行。 + +这个命令模式的实现将购物车操作和实际的执行逻辑解耦,允许客户端在不知道具体操作的情况下存储和执行命令。这对于支持撤销操作、记录命令历史、排队命令等高级功能非常有用。 + +''' \ No newline at end of file diff --git a/对象设计模式/行为型/190 备忘录.py b/对象设计模式/行为型/190 备忘录.py new file mode 100644 index 0000000..2231dff --- /dev/null +++ b/对象设计模式/行为型/190 备忘录.py @@ -0,0 +1,75 @@ +''' +备忘录模式(Memento Pattern): +在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 + +备忘录模式(Memento Pattern)可以用来保存和恢复书籍对象的内部状态, +例如用户可能想要保存他们当前阅读的书籍状态(比如阅读进度、高亮部分等),以便之后可以恢复到这个状态。 +''' + +# 书籍类,包含阅读状态 +class Book: + def __init__(self, title, author): + self.title = title + self.author = author + self.page = 1 # 初始页码 + self.highlights = [] # 高亮部分 + + def read(self, page): + self.page = page + print(f"Reading page {self.page} of '{self.title}' by {self.author}") + + def highlight(self, text): + self.highlights.append(text) + print(f"Highlighted text: {text}") + + def get_current_state(self): + return BookMemento(self.page, self.highlights[:]) + + def restore_state(self, memento): + self.page = memento.get_page() + self.highlights = memento.get_highlights() + +# 备忘录类,用于保存书籍状态 +class BookMemento: + def __init__(self, page, highlights): + self.page = page + self.highlights = highlights + + def get_page(self): + return self.page + + def get_highlights(self): + return self.highlights + +# 客户端代码 +if __name__ == "__main__": + # 创建书籍对象 + book = Book("The Hobbit", "J.R.R. Tolkien") + + # 阅读和高亮文本 + book.read(50) + book.highlight("Gollum's precious!") + + # 保存当前状态 + memento = book.get_current_state() + + # 改变状态 + book.read(100) + book.highlight("The dragon is coming!") + + # 恢复状态 + print("Restoring state...") + book.restore_state(memento) + print(f"Current page is {book.page}") + print("Highlighted texts:") + for highlight in book.highlights: + print(highlight) + + +''' +在这个示例中,Book 类代表了一本书,包含了页码和高亮部分等状态信息。BookMemento 类用于保存书籍的某一时刻的状态。Book 类提供了 get_current_state 方法来创建并返回一个包含当前阅读状态的 BookMemento 对象。同样地,Book 类也提供了 restore_state 方法来从 BookMemento 对象中恢复状态。 + +客户端代码创建了一个书籍对象,对其进行了阅读和高亮操作,然后保存了当前状态。之后改变了书籍的状态,并使用之前保存的状态恢复了书籍对象。 + +这样,用户就可以在需要的时候回到之前的阅读状态,无论是在同一个会话中还是在不同的会话中。这种模式在需要提供“撤销”或“恢复”功能的应用中非常有用。 +''' \ No newline at end of file diff --git a/对象设计模式/行为型/200 访问者.py b/对象设计模式/行为型/200 访问者.py new file mode 100644 index 0000000..3c0cf5e --- /dev/null +++ b/对象设计模式/行为型/200 访问者.py @@ -0,0 +1,72 @@ +''' +访问者模式(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 方法来接受访问者的访问。这样,访问者就可以对书籍执行相应的操作。 + +需要注意的是,访问者模式的一个主要缺点是增加新的操作意味着增加新的访问者类,这可能会导致类的数量增加。此外,如果需要在访问者中访问对象结构的复杂关系,代码可能会变得难以理解和维护。因此,在使用访问者模式时需要权衡其优缺点。 +''' \ No newline at end of file diff --git a/高性能模式/readme.md b/高性能模式/readme.md new file mode 100644 index 0000000..f37456e --- /dev/null +++ b/高性能模式/readme.md @@ -0,0 +1,7 @@ + +# 目标 +本节使用一个爬虫任务来展示如何追求代码的性能 。 + +# 任务 + +