前言
通用职责分配软件模式 GRASP(General Responsibility Assignment Software Principles)是一组用于在面向对象设计中分配职责的模式。它提供了一系列关于如何在对象之间分配职责的建议,以实现高内聚和低耦合的设计。GRASP模式包括:
- 信息专家(Information Expert):将职责分配给拥有完成该职责所需信息的类。
- 创建者(Creator):将创建对象的职责分配给与该对象存在某种关系的类。
- 控制器(Controller):将处理系统事件的职责分配给表示用例场景的类或表示系统中协调者的类。
- 低耦合(Low Coupling):尽量减少类与类之间的依赖关系。
- 高内聚(High Cohesion):尽量将相关的职责分配给同一个类。
- 多态(Polymorphism):通过接口或抽象基类来定义通用行为,让子类实现具体行为。
- 纯虚构(Pure Fabrication):创建一些没有直接映射到问题域的类,以更好地实现低耦合和高内聚。
- 间接性(Indirection):通过引入间接层来降低类之间的直接依赖。
- 隔离变化(Protected Variation):设计系统时,尽量减少对变化的部分的依赖。
一、纯虚构模式
纯虚构模式
- 名称:纯虚构 Pure Fabrication
- 应用场景:在某些情况下,没有一个自然的类来承担某个职责,或者将该职责分配给现有类会导致设计上的问题,如高耦合或低内聚。
- 解决方案:
- 纯虚构是指创建一个新的类来承担一个职责,即使这个类不代表问题领域中的任何真实实体。这个类纯粹是为了软件设计的目的而创建的。
- 把高度内聚(功能的相关性高)的职责分配给虚构出来的一个类,即使这个类在领域模型里没有对应的概念。
- 优点:保持系统的低耦合和高内聚,确保职责分配得当,从而提高软件的复用性
- 缺点:可能导致出现面向过程/功能的分析与设计
示例
一个库存管理系统,该系统需要计算订单的总价。这个计算过程可能涉及到多种逻辑,比如根据不同的客户类型应用不同的折扣,或者根据订单中商品的数量提供批量折扣。
- 首先,我们可以定义一些基本的类,如Product(代表商品)和Order(代表订单)。
- 然后,我们可以创建一个纯虚构的类PriceCalculator来处理计算订单总价的逻辑。
- PriceCalculator类是一个纯虚构的类,它不直接对应于问题领域中的任何实体。它的目的是封装计算订单总价的逻辑,使Order类保持简单和专注于订单管理。
- 通过这种方式,如果将来需要更改折扣逻辑或添加新的计算方法,我们只需要修改PriceCalculator类,而不需要修改Order类,这有助于保持系统的低耦合和高内聚。
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
class Order:
def __init__(self):
self.products: list[Product] = []
def add_product(self, product):
self.products.append(product)
def get_total_price(self):
"""使用纯虚构的PriceCalculator来计算总价"""
return PriceCalculator.calculate_total_price(self.products)
class PriceCalculator:
@staticmethod
def calculate_total_price(products: list[Product]):
"""计算总价:可扩展复杂的优惠计算逻辑"""
total_price = 0
for product in products:
total_price += product.price
total_price *= PriceCalculator.apply_discounts(products)
return total_price
@staticmethod
def apply_discounts(products: list[Product]):
"""订单中的商品数据大于5,9折"""
if len(products) > 5:
return 0.9
return 1
if __name__ == "__main__":
order = Order()
order.add_product(Product("Book", 12.99))
order.add_product(Product("Pen", 1.99))
order.add_product(Product("Notebook", 5.99))
order.add_product(Product("Pencil", 0.99))
order.add_product(Product("Eraser", 0.49))
order.add_product(Product("Ruler", 2.99))
order.add_product(Product("Highlighter", 3.99)) # 超过5件商品
print(f"订单总价为:{order.get_total_price():.2f}")
### 输出结果
订单总价为:26.49
二、间接性模式
间接性模式
- 名称: 间接性 Indirection
- 应用场景:把职责分配到哪里可以避免两个或者多个对象之间的直接耦合?如何解耦对象以保持较高的可重用性?
- 解决方案:把职责分配给一个中介对象,隔离对象与其他构件或者服务,使它们不产生直接耦合。
- 优点:有助于降低系统组件之间的耦合度,使得系统更加模块化、易于维护和扩展
示例
一个简单的聊天室应用,其中用户可以向聊天室发送消息,而聊天室将负责将消息广播给所有用户。
- 使用“中介者”模式来实现用户之间的间接通信。用户不直接与其他用户通信,而是通过ChatRoom中介者发送和接收消息。
- 减少了用户之间的直接依赖,使得添加新用户或更改消息传递逻辑变得更加容易。
class User:
def __init__(self, name):
self.name = name
self.mediator: ChatRoom = None
def send_msg(self, msg):
if self.mediator:
self.mediator.broadcast(self, msg)
def receive_msg(self, from_user: "User", msg):
print(f"{self.name} 收到来自 {from_user.name} 的消息:{msg}")
class ChatRoom:
def __init__(self):
self.users: list[User] = []
def add_user(self, user: User):
user.mediator = self
self.users.append(user)
def broadcast(self, from_user, msg):
for user in self.users:
# 广播给除自己以外的所有人
if user != from_user:
user.receive_msg(from_user, msg)
print("#" * 10)
chat_room = ChatRoom()
zhangs = User("张三")
lis = User("李四")
wangw = User("王五")
chat_room.add_user(zhangs)
chat_room.add_user(lis)
chat_room.add_user(wangw)
zhangs.send_msg("大家好,我叫张三")
lis.send_msg("你好,张三。很高兴认识你!")
### 输出结果
李四 收到来自 张三 的消息:大家好,我叫张三
王五 收到来自 张三 的消息:大家好,我叫张三
##########
张三 收到来自 李四 的消息:你好,张三。很高兴认识你!
王五 收到来自 李四 的消息:你好,张三。很高兴认识你!
##########
您正在阅读的是《面向对象分析与设计Python版》专栏!关注不迷路~