设计模型

dev
zj3D 8 months ago
parent c5932334fa
commit 1920e47a1c

@ -0,0 +1,22 @@
# 目标
本节使用一个书城的各种业务环节来展示面向对象的各种设计模式 。
# 任务
背景假设为一个综合书城,提供线上线下购买,还经营一个书吧、一个报告厅
# 说明
因为 Python 对象协议的机制,多态、接口概念发生了根本变化。
很多模式中,类的继承关系没必要了。下面示例中很多依旧保持了基类
一是致敬经典,二是起到一个工程上更工整强注释的作用
另外,Python的动态语言的特性 。使得一些C++、Java 的模式没用了。
比如 “ 原型模式Prototype可以使用copy.deepcopy()非常简便来创建。
面向对象设计模式是软件工程中一组经过验证的、可重复使用的解决方案,
用于解决在设计和实现面向对象系统时经常遇到的设计问题。
面向对象的模式把编程过程中的一些思路套路固定化,并给一个名字方便理解 。
所以,模式不是语法,而是编程思路。
那为啥,面向过程没有这么做?
是因为这个思维提炼过程,充分利用了面向对象语言的特性:封装、继承、多态。

@ -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

@ -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')

@ -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.")

@ -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

@ -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)

@ -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()

@ -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对象而不是直接访问
这种方式提供了一种灵活的控制机制使得可以在不修改原始类的情况下增加额外的功能或控制逻辑
'''

@ -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")

@ -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 是一个抽象类定义了所有组件无论是分类还是书籍都应该有的方法addremove display
Book 类是叶子节点代表具体的书籍它实现了 BookComponent 接口
add remove 方法对于书籍来说是不适用的因此它们只是打印一条错误消息
BookCategory 类是复合节点代表书籍的分类它可以包含其他分类或书籍因此它实现了 add remove 方法来管理子节点并且实现了 display 方法来显示分类及其子节点的信息
客户端代码创建了一些书籍和分类对象并构建了一个书籍分类结构最后通过调用根分类的 display 方法可以显示整个书籍分类结构
'''

@ -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 方法可以展示分类中的所有书籍
'''

@ -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)}")

@ -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) # 当添加商品时,库存系统和价格计算器都会收到更新通知

@ -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类本身。
################################################################################

@ -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()

@ -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')

@ -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基类它定义了一个处理请求的基本框架
具体的处理逻辑则在子类InventoryHandlerPricingHandler和NotificationHandler中实现
这些子类形成了职责链通过successor引用链接在一起
客户下了一个订单后这个订单请求会从库存处理器InventoryHandler开始处理
如果库存足够请求将被传递给价格处理器PricingHandler来计算总价
然后价格处理器再将请求传递给通知处理器NotificationHandler
最后发送通知给客户
如果任何处理器无法处理请求例如库存不足处理将在那里终止并且返回相应的结果
这个模式的好处是可以很容易地改变处理的顺序或者增加/删除处理器而不需要修改已有的代码
'''

@ -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和一个调用者InvokerInvoker可以存储并执行命令
具体命令类AddToCartCommand和RemoveFromCartCommand实现了Command接口并在execute方法中调用了ShoppingCart的相应操作
客户端代码创建了ShoppingCart实例和Invoker实例并创建了添加和移除购物车项的具体命令对象这些命令对象通过调用者的store_and_execute_command方法被存储和执行
这个命令模式的实现将购物车操作和实际的执行逻辑解耦允许客户端在不知道具体操作的情况下存储和执行命令这对于支持撤销操作记录命令历史排队命令等高级功能非常有用
'''

@ -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 对象中恢复状态
客户端代码创建了一个书籍对象对其进行了阅读和高亮操作然后保存了当前状态之后改变了书籍的状态并使用之前保存的状态恢复了书籍对象
这样用户就可以在需要的时候回到之前的阅读状态无论是在同一个会话中还是在不同的会话中这种模式在需要提供撤销恢复功能的应用中非常有用
'''

@ -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 方法来接受访问者的访问这样访问者就可以对书籍执行相应的操作
需要注意的是访问者模式的一个主要缺点是增加新的操作意味着增加新的访问者类这可能会导致类的数量增加此外如果需要在访问者中访问对象结构的复杂关系代码可能会变得难以理解和维护因此在使用访问者模式时需要权衡其优缺点
'''

@ -0,0 +1,7 @@
# 目标
本节使用一个爬虫任务来展示如何追求代码的性能 。
# 任务
Loading…
Cancel
Save