Skip to content

第10章 外观模式 ​

学习目标 ​

完成本章学习后,读者将能够:

  • 理解外观模式的核心概念与数学形式化定义
  • 掌握简化复杂系统接口的设计方法
  • 运用外观模式降低系统耦合度
  • 实现多层外观与可扩展外观模式
  • 识别外观模式的适用场景与反模式
  • 设计企业级外观模式解决方案

10.1 模式定义 ​

10.1.1 核心定义 ​

外观模式(Facade Pattern) 为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式是一种结构型模式,它通过封装复杂的子系统,为客户端提供一个简化的调用入口。

10.1.2 形式化定义 ​

设 $\mathcal{S} = {S_1, S_2, ..., S_n}$ 为子系统集合,每个子系统 $S_i$ 提供操作集合 $O_i = {o_{i1}, o_{i2}, ..., o_{im}}$。外观模式可形式化定义为:

$$\text{Facade}: \mathcal{F} \rightarrow \bigcup_{i=1}^{n} O_i$$

其中 $\mathcal{F}$ 为外观接口,满足:

$$\forall f \in \mathcal{F}: f = \phi(o_{1j}, o_{2k}, ..., o_{nl})$$

$\phi$ 为操作组合函数,将多个子系统操作封装为单一外观操作。

接口简化度:

$$\text{Simplification} = \frac{|\mathcal{F}|}{|\bigcup_{i=1}^{n} O_i|}$$

耦合度降低:

$$\text{Coupling}{\text{with_facade}} = \frac{\text{Client} \rightarrow \text{Facade}}{\text{Client} \rightarrow \sum^{n} S_i}$$

迪米特法则满足度:

$$\text{LoD Compliance} = \begin{cases} 1 & \text{if Client only knows Facade} \ 0 & \text{otherwise} \end{cases}$$

复杂度分析:

  • 外观创建:$O(n)$($n$ 为子系统数量)
  • 操作调用:$O(1)$(单一入口点)
  • 空间复杂度:$O(n)$(持有子系统引用)

10.1.3 历史背景与学术脉络 ​

外观模式起源于软件架构分层的设计实践。其学术发展历程如下:

年份里程碑贡献者
1970s分层架构概念提出Dijkstra
1987ET++框架中的外观应用Weinand, Gamma
1994GoF《设计模式》正式收录Gang of Four
1996与迪米特法则关联研究Lieberherr
2002API设计中的外观应用Bloch
2010微服务外观模式研究Richardson
2018API网关作为外观模式云原生社区

学术意义:外观模式是**迪米特法则(LoD)**的典型应用,体现了"最少知识原则"的设计思想,为复杂系统的简化访问提供了范式解决方案。在微服务架构中,API网关模式是外观模式的现代演进。


10.2 模式结构与参与者 ​

10.2.1 UML类图 ​

┌─────────────────────────────────────────────────────────────────────────┐
│                              Client                                      │
└───────────────────────────────────┬─────────────────────────────────────┘
                                    │ uses
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                              Facade                                      │
├─────────────────────────────────────────────────────────────────────────┤
│ - subsystemA: SubsystemA                                                │
│ - subsystemB: SubsystemB                                                │
│ - subsystemC: SubsystemC                                                │
├─────────────────────────────────────────────────────────────────────────┤
│ + operation1(): Result                                                  │
│ + operation2(): Result                                                  │
│ + operation3(): Result                                                  │
└───────────────────────────────────┬─────────────────────────────────────┘
                                    │ delegates to
        ┌───────────────────────────┼───────────────────────────┐
        │                           │                           │
        ▼                           ▼                           ▼
┌───────────────┐           ┌───────────────┐           ┌───────────────┐
│  SubsystemA   │           │  SubsystemB   │           │  SubsystemC   │
├───────────────┤           ├───────────────┤           ├───────────────┤
│ + methodA1()  │           │ + methodB1()  │           │ + methodC1()  │
│ + methodA2()  │           │ + methodB2()  │           │ + methodC2()  │
│ + methodA3()  │           │ + methodB3()  │           │ + methodC3()  │
└───────────────┘           └───────────────┘           └───────────────┘

10.2.2 参与者职责 ​

参与者职责关键特征
Facade提供简化接口,委托子系统操作知道哪些子系统负责处理请求
Subsystem实现专业功能,处理外观委派的任务不知道外观的存在
Client通过外观与子系统交互不直接访问子系统

10.2.3 调用流程 ​

Client                    Facade                 SubsystemA    SubsystemB    SubsystemC
  │                         │                        │             │             │
  │──── operation1() ──────>│                        │             │             │
  │                         │──── methodA1() ───────>│             │             │
  │                         │<─── result A ──────────│             │             │
  │                         │──── methodB1() ────────────────────>│             │
  │                         │<─── result B ────────────────────────────────────│
  │                         │──── methodC1() ────────────────────────────────────────────>│
  │                         │<─── result C ──────────────────────────────────────────────│
  │<─── combined result ────│                        │             │             │
  │                         │                        │             │             │

10.3 Python实现 ​

10.3.1 标准实现 ​

python
from typing import Any, Dict, List, Optional
from dataclasses import dataclass

class SubsystemA:
    """子系统A - 负责数据处理"""
    
    def operation_a1(self) -> str:
        return "SubsystemA: 数据验证完成"
    
    def operation_a2(self) -> str:
        return "SubsystemA: 数据转换完成"
    
    def process_data(self, data: Any) -> Dict[str, Any]:
        return {"processed": True, "data": data}


class SubsystemB:
    """子系统B - 负责业务逻辑"""
    
    def operation_b1(self) -> str:
        return "SubsystemB: 业务规则检查完成"
    
    def operation_b2(self) -> str:
        return "SubsystemB: 业务计算完成"
    
    def apply_business_rules(self, data: Dict) -> Dict:
        data["business_applied"] = True
        return data


class SubsystemC:
    """子系统C - 负责存储"""
    
    def operation_c1(self) -> str:
        return "SubsystemC: 存储准备完成"
    
    def operation_c2(self) -> str:
        return "SubsystemC: 数据持久化完成"
    
    def save(self, data: Dict) -> bool:
        print(f"保存数据: {data}")
        return True


class Facade:
    """外观类 - 提供简化接口"""
    
    def __init__(self):
        self._subsystem_a = SubsystemA()
        self._subsystem_b = SubsystemB()
        self._subsystem_c = SubsystemC()
    
    def operation1(self) -> str:
        """简化操作1 - 初始化流程"""
        results = [
            "Facade: 初始化子系统",
            self._subsystem_a.operation_a1(),
            self._subsystem_b.operation_b1(),
            self._subsystem_c.operation_c1(),
        ]
        return "\n".join(results)
    
    def operation2(self) -> str:
        """简化操作2 - 执行流程"""
        results = [
            "Facade: 执行复杂操作",
            self._subsystem_a.operation_a2(),
            self._subsystem_b.operation_b2(),
            self._subsystem_c.operation_c2(),
        ]
        return "\n".join(results)
    
    def process_complete(self, data: Any) -> Dict[str, Any]:
        """完整处理流程"""
        result = self._subsystem_a.process_data(data)
        result = self._subsystem_b.apply_business_rules(result)
        success = self._subsystem_c.save(result)
        return {"success": success, "result": result}


def client_code(facade: Facade) -> None:
    """客户端代码 - 仅与外观交互"""
    print(facade.operation1())
    print()
    print(facade.operation2())
    print()
    print(facade.process_complete({"input": "test"}))


if __name__ == "__main__":
    facade = Facade()
    client_code(facade)

10.3.2 Protocol实现(结构化类型) ​

python
from typing import Protocol, runtime_checkable, Dict, Any, List, Optional
from dataclasses import dataclass

@runtime_checkable
class SubsystemProtocol(Protocol):
    """子系统协议"""
    
    def initialize(self) -> bool: ...
    def process(self, data: Dict[str, Any]) -> Dict[str, Any]: ...
    def cleanup(self) -> None: ...


@dataclass
class ValidationSubsystem:
    """验证子系统"""
    
    def initialize(self) -> bool:
        print("验证子系统初始化")
        return True
    
    def process(self, data: Dict[str, Any]) -> Dict[str, Any]:
        if not data.get("value"):
            raise ValueError("缺少必要字段")
        data["validated"] = True
        return data
    
    def cleanup(self) -> None:
        print("验证子系统清理")


@dataclass
class TransformSubsystem:
    """转换子系统"""
    
    def initialize(self) -> bool:
        print("转换子系统初始化")
        return True
    
    def process(self, data: Dict[str, Any]) -> Dict[str, Any]:
        data["transformed"] = True
        data["value"] = str(data.get("value", "")).upper()
        return data
    
    def cleanup(self) -> None:
        print("转换子系统清理")


@dataclass
class StorageSubsystem:
    """存储子系统"""
    
    def initialize(self) -> bool:
        print("存储子系统初始化")
        return True
    
    def process(self, data: Dict[str, Any]) -> Dict[str, Any]:
        data["stored"] = True
        print(f"存储数据: {data}")
        return data
    
    def cleanup(self) -> None:
        print("存储子系统清理")


class ModularFacade:
    """模块化外观 - 支持动态子系统"""
    
    def __init__(self):
        self._subsystems: List[SubsystemProtocol] = []
    
    def register_subsystem(self, subsystem: SubsystemProtocol) -> None:
        self._subsystems.append(subsystem)
    
    def initialize_all(self) -> bool:
        results = [s.initialize() for s in self._subsystems]
        return all(results)
    
    def process_pipeline(self, data: Dict[str, Any]) -> Dict[str, Any]:
        result = data.copy()
        for subsystem in self._subsystems:
            result = subsystem.process(result)
        return result
    
    def cleanup_all(self) -> None:
        for subsystem in self._subsystems:
            subsystem.cleanup()


if __name__ == "__main__":
    facade = ModularFacade()
    facade.register_subsystem(ValidationSubsystem())
    facade.register_subsystem(TransformSubsystem())
    facade.register_subsystem(StorageSubsystem())
    
    facade.initialize_all()
    result = facade.process_pipeline({"value": "hello world"})
    print(f"\n处理结果: {result}")
    facade.cleanup_all()

10.3.3 泛型实现(类型安全) ​

python
from abc import ABC, abstractmethod
from typing import TypeVar, Generic, Dict, Any, List, Optional, Callable
from dataclasses import dataclass

T = TypeVar('T')
R = TypeVar('R')


class SubsystemBase(ABC, Generic[T, R]):
    """子系统基类"""
    
    @abstractmethod
    def process(self, input_data: T) -> R:
        pass
    
    @abstractmethod
    def get_name(self) -> str:
        pass


class GenericFacade(Generic[T, R]):
    """泛型外观"""
    
    def __init__(self):
        self._subsystems: List[SubsystemBase] = []
        self._preprocessors: List[Callable] = []
        self._postprocessors: List[Callable] = []
    
    def add_subsystem(self, subsystem: SubsystemBase) -> 'GenericFacade':
        self._subsystems.append(subsystem)
        return self
    
    def add_preprocessor(self, processor: Callable) -> 'GenericFacade':
        self._preprocessors.append(processor)
        return self
    
    def add_postprocessor(self, processor: Callable) -> 'GenericFacade':
        self._postprocessors.append(processor)
        return self
    
    def execute(self, input_data: T) -> R:
        data = input_data
        
        for preprocessor in self._preprocessors:
            data = preprocessor(data)
        
        for subsystem in self._subsystems:
            data = subsystem.process(data)
        
        for postprocessor in self._postprocessors:
            data = postprocessor(data)
        
        return data


@dataclass
class StringValidationSubsystem(SubsystemBase[str, str]):
    """字符串验证子系统"""
    
    def process(self, input_data: str) -> str:
        if not input_data:
            raise ValueError("输入不能为空")
        return input_data.strip()
    
    def get_name(self) -> str:
        return "StringValidation"


@dataclass
class StringTransformSubsystem(SubsystemBase[str, str]):
    """字符串转换子系统"""
    
    def process(self, input_data: str) -> str:
        return input_data.upper()
    
    def get_name(self) -> str:
        return "StringTransform"


@dataclass
class StringFormattingSubsystem(SubsystemBase[str, Dict[str, Any]]):
    """字符串格式化子系统"""
    
    def process(self, input_data: str) -> Dict[str, Any]:
        return {
            "original": input_data,
            "length": len(input_data),
            "words": len(input_data.split()),
            "formatted": f"[{input_data}]"
        }
    
    def get_name(self) -> str:
        return "StringFormatting"


if __name__ == "__main__":
    facade: GenericFacade[str, Dict[str, Any]] = GenericFacade()
    facade.add_subsystem(StringValidationSubsystem())
    facade.add_subsystem(StringTransformSubsystem())
    facade.add_subsystem(StringFormattingSubsystem())
    
    result = facade.execute("  hello world  ")
    print(f"处理结果: {result}")

10.3.4 可配置外观 ​

python
from typing import Any, Dict, List, Optional, Callable, Type
from dataclasses import dataclass, field
from enum import Enum

class OperationMode(Enum):
    STRICT = "strict"
    LENIENT = "lenient"
    DEBUG = "debug"


@dataclass
class FacadeConfig:
    """外观配置"""
    mode: OperationMode = OperationMode.STRICT
    enable_logging: bool = True
    enable_caching: bool = False
    max_retries: int = 3
    timeout: float = 30.0


class ConfigurableFacade:
    """可配置外观"""
    
    def __init__(self, config: FacadeConfig = None):
        self._config = config or FacadeConfig()
        self._subsystems: Dict[str, Any] = {}
        self._operations: Dict[str, Callable] = {}
        self._cache: Dict[str, Any] = {}
    
    def register_subsystem(self, name: str, subsystem: Any) -> None:
        self._subsystems[name] = subsystem
    
    def register_operation(
        self, 
        name: str, 
        operation: Callable,
        subsystems: List[str] = None
    ) -> None:
        self._operations[name] = {
            "handler": operation,
            "subsystems": subsystems or []
        }
    
    def execute(self, operation_name: str, *args, **kwargs) -> Any:
        if operation_name not in self._operations:
            raise ValueError(f"未知操作: {operation_name}")
        
        op_config = self._operations[operation_name]
        
        if self._config.enable_logging:
            print(f"[LOG] 执行操作: {operation_name}")
        
        if self._config.enable_caching:
            cache_key = f"{operation_name}:{args}:{kwargs}"
            if cache_key in self._cache:
                return self._cache[cache_key]
        
        try:
            result = op_config["handler"](*args, **kwargs)
            
            if self._config.enable_caching:
                self._cache[cache_key] = result
            
            return result
        except Exception as e:
            if self._config.mode == OperationMode.STRICT:
                raise
            elif self._config.mode == OperationMode.LENIENT:
                print(f"[ERROR] 操作失败: {e}")
                return None
            elif self._config.mode == OperationMode.DEBUG:
                import traceback
                traceback.print_exc()
                raise
    
    def get_subsystem(self, name: str) -> Optional[Any]:
        return self._subsystems.get(name)
    
    def list_operations(self) -> List[str]:
        return list(self._operations.keys())
    
    def clear_cache(self) -> None:
        self._cache.clear()


if __name__ == "__main__":
    class MockDatabase:
        def query(self, sql: str) -> List[Dict]:
            return [{"id": 1, "name": "test"}]
    
    class MockCache:
        def get(self, key: str) -> Optional[Any]:
            return None
        def set(self, key: str, value: Any) -> None:
            pass
    
    config = FacadeConfig(
        mode=OperationMode.DEBUG,
        enable_logging=True,
        enable_caching=True
    )
    
    facade = ConfigurableFacade(config)
    facade.register_subsystem("database", MockDatabase())
    facade.register_subsystem("cache", MockCache())
    
    facade.register_operation(
        "get_users",
        lambda: facade.get_subsystem("database").query("SELECT * FROM users")
    )
    
    print(f"可用操作: {facade.list_operations()}")
    result = facade.execute("get_users")
    print(f"查询结果: {result}")

10.4 实际应用示例 ​

10.4.1 电商订单处理系统 ​

python
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional
from datetime import datetime
from enum import Enum
import uuid

class OrderStatus(Enum):
    PENDING = "pending"
    CONFIRMED = "confirmed"
    PAID = "paid"
    SHIPPED = "shipped"
    DELIVERED = "delivered"
    CANCELLED = "cancelled"


@dataclass
class Product:
    id: str
    name: str
    price: float
    stock: int


@dataclass
class OrderItem:
    product_id: str
    product_name: str
    quantity: int
    unit_price: float
    
    @property
    def total(self) -> float:
        return self.quantity * self.unit_price


@dataclass
class Order:
    id: str = field(default_factory=lambda: str(uuid.uuid4())[:8])
    customer_id: str = ""
    items: List[OrderItem] = field(default_factory=list)
    shipping_address: str = ""
    status: OrderStatus = OrderStatus.PENDING
    created_at: datetime = field(default_factory=datetime.now)
    payment_id: Optional[str] = None
    shipment_id: Optional[str] = None
    
    @property
    def total_amount(self) -> float:
        return sum(item.total for item in self.items)


class InventoryService:
    """库存服务"""
    
    def __init__(self):
        self._inventory: Dict[str, int] = {}
    
    def set_stock(self, product_id: str, quantity: int) -> None:
        self._inventory[product_id] = quantity
    
    def check_availability(self, product_id: str, quantity: int) -> bool:
        available = self._inventory.get(product_id, 0)
        return available >= quantity
    
    def reserve(self, product_id: str, quantity: int) -> bool:
        if not self.check_availability(product_id, quantity):
            return False
        self._inventory[product_id] -= quantity
        return True
    
    def release(self, product_id: str, quantity: int) -> None:
        self._inventory[product_id] = self._inventory.get(product_id, 0) + quantity


class PaymentService:
    """支付服务"""
    
    def __init__(self):
        self._transactions: Dict[str, Dict] = {}
    
    def process_payment(
        self, 
        order_id: str, 
        amount: float, 
        method: str
    ) -> str:
        transaction_id = f"TXN-{uuid.uuid4().hex[:8]}"
        self._transactions[transaction_id] = {
            "order_id": order_id,
            "amount": amount,
            "method": method,
            "status": "completed",
            "created_at": datetime.now()
        }
        print(f"支付处理: {transaction_id}, 金额: ¥{amount:.2f}")
        return transaction_id
    
    def refund(self, transaction_id: str) -> bool:
        if transaction_id in self._transactions:
            self._transactions[transaction_id]["status"] = "refunded"
            print(f"退款处理: {transaction_id}")
            return True
        return False


class ShippingService:
    """物流服务"""
    
    def __init__(self):
        self._shipments: Dict[str, Dict] = {}
    
    def create_shipment(
        self, 
        order_id: str, 
        address: str
    ) -> str:
        shipment_id = f"SHP-{uuid.uuid4().hex[:8]}"
        self._shipments[shipment_id] = {
            "order_id": order_id,
            "address": address,
            "status": "pending",
            "created_at": datetime.now()
        }
        print(f"创建发货单: {shipment_id}, 地址: {address}")
        return shipment_id
    
    def track(self, shipment_id: str) -> Dict[str, Any]:
        return self._shipments.get(shipment_id, {})


class NotificationService:
    """通知服务"""
    
    def send_order_confirmation(
        self, 
        email: str, 
        order_id: str
    ) -> None:
        print(f"发送订单确认邮件到 {email}: 订单 {order_id}")
    
    def send_shipping_notification(
        self, 
        email: str, 
        shipment_id: str
    ) -> None:
        print(f"发送发货通知到 {email}: 发货单 {shipment_id}")
    
    def send_sms(self, phone: str, message: str) -> None:
        print(f"发送短信到 {phone}: {message}")


class LoyaltyService:
    """会员积分服务"""
    
    def __init__(self):
        self._points: Dict[str, int] = {}
    
    def earn_points(
        self, 
        customer_id: str, 
        amount: float
    ) -> int:
        points = int(amount / 10)
        self._points[customer_id] = self._points.get(customer_id, 0) + points
        print(f"积分入账: 客户 {customer_id}, +{points} 积分")
        return points
    
    def get_points(self, customer_id: str) -> int:
        return self._points.get(customer_id, 0)


class OrderFacade:
    """订单外观 - 统一订单处理接口"""
    
    def __init__(self):
        self._inventory = InventoryService()
        self._payment = PaymentService()
        self._shipping = ShippingService()
        self._notification = NotificationService()
        self._loyalty = LoyaltyService()
        self._orders: Dict[str, Order] = {}
    
    def create_order(
        self,
        customer_id: str,
        items: List[Dict[str, Any]],
        shipping_address: str
    ) -> Order:
        """创建订单"""
        order = Order(
            customer_id=customer_id,
            shipping_address=shipping_address
        )
        
        for item in items:
            order_item = OrderItem(
                product_id=item["product_id"],
                product_name=item["product_name"],
                quantity=item["quantity"],
                unit_price=item["unit_price"]
            )
            order.items.append(order_item)
        
        self._orders[order.id] = order
        print(f"创建订单: {order.id}, 客户: {customer_id}")
        return order
    
    def confirm_order(self, order_id: str) -> bool:
        """确认订单 - 检查并预留库存"""
        order = self._orders.get(order_id)
        if not order:
            return False
        
        reserved_items = []
        try:
            for item in order.items:
                if not self._inventory.reserve(item.product_id, item.quantity):
                    raise ValueError(f"库存不足: {item.product_id}")
                reserved_items.append(item)
            
            order.status = OrderStatus.CONFIRMED
            print(f"订单确认: {order_id}")
            return True
        except ValueError as e:
            for item in reserved_items:
                self._inventory.release(item.product_id, item.quantity)
            print(f"订单确认失败: {e}")
            return False
    
    def process_payment(
        self,
        order_id: str,
        payment_method: str
    ) -> bool:
        """处理支付"""
        order = self._orders.get(order_id)
        if not order or order.status != OrderStatus.CONFIRMED:
            return False
        
        try:
            transaction_id = self._payment.process_payment(
                order_id,
                order.total_amount,
                payment_method
            )
            order.payment_id = transaction_id
            order.status = OrderStatus.PAID
            print(f"支付完成: {order_id}")
            return True
        except Exception as e:
            print(f"支付失败: {e}")
            return False
    
    def ship_order(
        self,
        order_id: str,
        customer_email: str
    ) -> bool:
        """发货"""
        order = self._orders.get(order_id)
        if not order or order.status != OrderStatus.PAID:
            return False
        
        shipment_id = self._shipping.create_shipment(
            order_id,
            order.shipping_address
        )
        order.shipment_id = shipment_id
        order.status = OrderStatus.SHIPPED
        
        self._notification.send_shipping_notification(customer_email, shipment_id)
        
        self._loyalty.earn_points(order.customer_id, order.total_amount)
        
        print(f"发货完成: {order_id}")
        return True
    
    def place_order(
        self,
        customer_id: str,
        items: List[Dict[str, Any]],
        shipping_address: str,
        payment_method: str,
        customer_email: str
    ) -> Dict[str, Any]:
        """一键下单 - 完整流程"""
        print("\n=== 开始处理订单 ===")
        
        order = self.create_order(customer_id, items, shipping_address)
        
        if not self.confirm_order(order.id):
            return {"success": False, "error": "库存不足"}
        
        if not self.process_payment(order.id, payment_method):
            self.cancel_order(order.id)
            return {"success": False, "error": "支付失败"}
        
        self._notification.send_order_confirmation(customer_email, order.id)
        
        if not self.ship_order(order.id, customer_email):
            return {"success": False, "error": "发货失败"}
        
        print("=== 订单处理完成 ===\n")
        return {
            "success": True,
            "order_id": order.id,
            "payment_id": order.payment_id,
            "shipment_id": order.shipment_id,
            "total_amount": order.total_amount
        }
    
    def cancel_order(self, order_id: str) -> bool:
        """取消订单"""
        order = self._orders.get(order_id)
        if not order:
            return False
        
        if order.status in [OrderStatus.SHIPPED, OrderStatus.DELIVERED]:
            print("无法取消已发货或已送达的订单")
            return False
        
        for item in order.items:
            self._inventory.release(item.product_id, item.quantity)
        
        if order.payment_id:
            self._payment.refund(order.payment_id)
        
        order.status = OrderStatus.CANCELLED
        print(f"订单已取消: {order_id}")
        return True
    
    def get_order(self, order_id: str) -> Optional[Order]:
        return self._orders.get(order_id)
    
    def set_product_stock(self, product_id: str, quantity: int) -> None:
        self._inventory.set_stock(product_id, quantity)


if __name__ == "__main__":
    facade = OrderFacade()
    
    facade.set_product_stock("PROD-001", 100)
    facade.set_product_stock("PROD-002", 50)
    
    result = facade.place_order(
        customer_id="CUST-001",
        items=[
            {"product_id": "PROD-001", "product_name": "Python教程", "quantity": 2, "unit_price": 99.0},
            {"product_id": "PROD-002", "product_name": "设计模式书籍", "quantity": 1, "unit_price": 128.0}
        ],
        shipping_address="北京市朝阳区xxx街道",
        payment_method="credit_card",
        customer_email="customer@example.com"
    )
    
    print(f"\n订单结果: {result}")

10.4.2 数据库操作外观 ​

python
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, TypeVar, Generic, Callable
from contextlib import contextmanager
from enum import Enum
import time

T = TypeVar('T')


class ConnectionStatus(Enum):
    DISCONNECTED = "disconnected"
    CONNECTED = "connected"
    ERROR = "error"


@dataclass
class ConnectionConfig:
    host: str
    port: int
    database: str
    username: str
    password: str
    pool_size: int = 5
    timeout: float = 30.0


@dataclass
class QueryResult:
    success: bool
    data: List[Dict[str, Any]] = field(default_factory=list)
    affected_rows: int = 0
    error: Optional[str] = None
    execution_time: float = 0.0


class ConnectionPool:
    """连接池"""
    
    def __init__(self, config: ConnectionConfig):
        self._config = config
        self._connections: List[Any] = []
        self._available: List[Any] = []
        self._status = ConnectionStatus.DISCONNECTED
    
    def initialize(self) -> bool:
        print(f"初始化连接池: {self._config.host}:{self._config.port}")
        for _ in range(self._config.pool_size):
            conn = self._create_connection()
            self._connections.append(conn)
            self._available.append(conn)
        self._status = ConnectionStatus.CONNECTED
        return True
    
    def _create_connection(self) -> Any:
        return {"id": id(self), "created_at": time.time()}
    
    def acquire(self) -> Any:
        if not self._available:
            raise RuntimeError("连接池已满")
        return self._available.pop()
    
    def release(self, conn: Any) -> None:
        self._available.append(conn)
    
    def close_all(self) -> None:
        self._connections.clear()
        self._available.clear()
        self._status = ConnectionStatus.DISCONNECTED
    
    @property
    def status(self) -> ConnectionStatus:
        return self._status


class QueryBuilder:
    """查询构建器"""
    
    def select(
        self, 
        table: str, 
        columns: List[str] = None,
        where: Dict[str, Any] = None,
        order_by: str = None,
        limit: int = None
    ) -> str:
        cols = ", ".join(columns) if columns else "*"
        sql = f"SELECT {cols} FROM {table}"
        
        if where:
            conditions = [f"{k} = %s" for k in where.keys()]
            sql += f" WHERE {' AND '.join(conditions)}"
        
        if order_by:
            sql += f" ORDER BY {order_by}"
        
        if limit:
            sql += f" LIMIT {limit}"
        
        return sql
    
    def insert(self, table: str, data: Dict[str, Any]) -> str:
        columns = ", ".join(data.keys())
        placeholders = ", ".join(["%s"] * len(data))
        return f"INSERT INTO {table} ({columns}) VALUES ({placeholders})"
    
    def update(
        self, 
        table: str, 
        data: Dict[str, Any], 
        where: Dict[str, Any]
    ) -> str:
        sets = ", ".join([f"{k} = %s" for k in data.keys()])
        conditions = " AND ".join([f"{k} = %s" for k in where.keys()])
        return f"UPDATE {table} SET {sets} WHERE {conditions}"
    
    def delete(self, table: str, where: Dict[str, Any]) -> str:
        conditions = " AND ".join([f"{k} = %s" for k in where.keys()])
        return f"DELETE FROM {table} WHERE {conditions}"


class QueryExecutor:
    """查询执行器"""
    
    def execute(
        self, 
        conn: Any, 
        sql: str, 
        params: tuple = ()
    ) -> QueryResult:
        start_time = time.time()
        
        try:
            print(f"执行SQL: {sql}")
            if params:
                print(f"参数: {params}")
            
            mock_data = [{"id": i, "name": f"record_{i}"} for i in range(1, 4)]
            
            execution_time = time.time() - start_time
            return QueryResult(
                success=True,
                data=mock_data,
                affected_rows=len(mock_data),
                execution_time=execution_time
            )
        except Exception as e:
            return QueryResult(
                success=False,
                error=str(e),
                execution_time=time.time() - start_time
            )


class TransactionManager:
    """事务管理器"""
    
    def __init__(self, executor: QueryExecutor, pool: ConnectionPool):
        self._executor = executor
        self._pool = pool
        self._connection = None
        self._active = False
    
    def begin(self) -> None:
        self._connection = self._pool.acquire()
        self._active = True
        print("BEGIN TRANSACTION")
    
    def commit(self) -> None:
        print("COMMIT")
        self._pool.release(self._connection)
        self._active = False
    
    def rollback(self) -> None:
        print("ROLLBACK")
        self._pool.release(self._connection)
        self._active = False
    
    def execute(self, sql: str, params: tuple = ()) -> QueryResult:
        if not self._active:
            raise RuntimeError("事务未激活")
        return self._executor.execute(self._connection, sql, params)


class CacheLayer:
    """缓存层"""
    
    def __init__(self):
        self._cache: Dict[str, Any] = {}
        self._ttl: Dict[str, float] = {}
    
    def get(self, key: str) -> Optional[Any]:
        if key in self._cache:
            if time.time() < self._ttl.get(key, 0):
                return self._cache[key]
            del self._cache[key]
            del self._ttl[key]
        return None
    
    def set(self, key: str, value: Any, ttl: float = 300) -> None:
        self._cache[key] = value
        self._ttl[key] = time.time() + ttl
    
    def delete(self, key: str) -> None:
        self._cache.pop(key, None)
        self._ttl.pop(key, None)
    
    def clear(self) -> None:
        self._cache.clear()
        self._ttl.clear()


class DatabaseFacade:
    """数据库外观 - 统一数据库操作接口"""
    
    def __init__(self, config: ConnectionConfig):
        self._pool = ConnectionPool(config)
        self._query_builder = QueryBuilder()
        self._executor = QueryExecutor()
        self._cache = CacheLayer()
        self._transaction: Optional[TransactionManager] = None
    
    def connect(self) -> bool:
        return self._pool.initialize()
    
    def disconnect(self) -> None:
        self._pool.close_all()
        self._cache.clear()
    
    def find_all(
        self, 
        table: str, 
        columns: List[str] = None,
        where: Dict[str, Any] = None,
        use_cache: bool = True
    ) -> QueryResult:
        cache_key = f"find_all:{table}:{columns}:{where}"
        
        if use_cache:
            cached = self._cache.get(cache_key)
            if cached:
                return QueryResult(success=True, data=cached)
        
        sql = self._query_builder.select(table, columns, where)
        params = tuple(where.values()) if where else ()
        
        conn = self._pool.acquire()
        try:
            result = self._executor.execute(conn, sql, params)
            if result.success and use_cache:
                self._cache.set(cache_key, result.data)
            return result
        finally:
            self._pool.release(conn)
    
    def find_one(
        self, 
        table: str, 
        where: Dict[str, Any],
        columns: List[str] = None
    ) -> QueryResult:
        sql = self._query_builder.select(table, columns, where, limit=1)
        params = tuple(where.values())
        
        conn = self._pool.acquire()
        try:
            result = self._executor.execute(conn, sql, params)
            if result.success and result.data:
                return QueryResult(success=True, data=[result.data[0]])
            return QueryResult(success=True, data=[])
        finally:
            self._pool.release(conn)
    
    def insert(self, table: str, data: Dict[str, Any]) -> QueryResult:
        sql = self._query_builder.insert(table, data)
        params = tuple(data.values())
        
        conn = self._pool.acquire()
        try:
            result = self._executor.execute(conn, sql, params)
            self._invalidate_cache(table)
            return result
        finally:
            self._pool.release(conn)
    
    def update(
        self, 
        table: str, 
        data: Dict[str, Any], 
        where: Dict[str, Any]
    ) -> QueryResult:
        sql = self._query_builder.update(table, data, where)
        params = tuple(data.values()) + tuple(where.values())
        
        conn = self._pool.acquire()
        try:
            result = self._executor.execute(conn, sql, params)
            self._invalidate_cache(table)
            return result
        finally:
            self._pool.release(conn)
    
    def delete(self, table: str, where: Dict[str, Any]) -> QueryResult:
        sql = self._query_builder.delete(table, where)
        params = tuple(where.values())
        
        conn = self._pool.acquire()
        try:
            result = self._executor.execute(conn, sql, params)
            self._invalidate_cache(table)
            return result
        finally:
            self._pool.release(conn)
    
    @contextmanager
    def transaction(self):
        """事务上下文管理器"""
        tx = TransactionManager(self._executor, self._pool)
        try:
            tx.begin()
            yield tx
            tx.commit()
        except Exception as e:
            tx.rollback()
            raise
    
    def _invalidate_cache(self, table: str) -> None:
        keys_to_delete = [k for k in self._cache._cache if f":{table}:" in k]
        for key in keys_to_delete:
            self._cache.delete(key)
    
    @property
    def status(self) -> ConnectionStatus:
        return self._pool.status


if __name__ == "__main__":
    config = ConnectionConfig(
        host="localhost",
        port=3306,
        database="myapp",
        username="root",
        password="password"
    )
    
    db = DatabaseFacade(config)
    db.connect()
    
    print("=== 查询所有用户 ===")
    result = db.find_all("users", ["id", "name", "email"])
    print(f"结果: {result.data}")
    
    print("\n=== 查询单个用户 ===")
    result = db.find_one("users", {"id": 1})
    print(f"结果: {result.data}")
    
    print("\n=== 插入用户 ===")
    result = db.insert("users", {"name": "张三", "email": "zhangsan@example.com"})
    print(f"成功: {result.success}")
    
    print("\n=== 事务操作 ===")
    with db.transaction() as tx:
        tx.execute("INSERT INTO users (name) VALUES (%s)", ("李四",))
        tx.execute("UPDATE users SET name = %s WHERE id = %s", ("王五", 1))
    
    db.disconnect()

10.4.3 智能家居控制系统 ​

python
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Callable
from enum import Enum
from datetime import datetime, time
import json


class DeviceState(Enum):
    ON = "on"
    OFF = "off"
    STANDBY = "standby"


class DeviceType(Enum):
    LIGHT = "light"
    AIR_CONDITIONER = "air_conditioner"
    TV = "tv"
    CURTAIN = "curtain"
    SPEAKER = "speaker"
    CAMERA = "camera"


@dataclass
class DeviceStatus:
    device_id: str
    device_name: str
    device_type: DeviceType
    state: DeviceState
    properties: Dict[str, Any] = field(default_factory=dict)
    last_updated: datetime = field(default_factory=datetime.now)


class Light:
    """灯光设备"""
    
    def __init__(self, device_id: str, name: str):
        self.device_id = device_id
        self.name = name
        self.state = DeviceState.OFF
        self.brightness = 100
        self.color = "#FFFFFF"
    
    def turn_on(self) -> None:
        self.state = DeviceState.ON
        print(f"💡 {self.name} 已开启")
    
    def turn_off(self) -> None:
        self.state = DeviceState.OFF
        print(f"💡 {self.name} 已关闭")
    
    def set_brightness(self, level: int) -> None:
        self.brightness = max(0, min(100, level))
        print(f"💡 {self.name} 亮度: {self.brightness}%")
    
    def set_color(self, color: str) -> None:
        self.color = color
        print(f"💡 {self.name} 颜色: {color}")
    
    def get_status(self) -> DeviceStatus:
        return DeviceStatus(
            device_id=self.device_id,
            device_name=self.name,
            device_type=DeviceType.LIGHT,
            state=self.state,
            properties={
                "brightness": self.brightness,
                "color": self.color
            }
        )


class AirConditioner:
    """空调设备"""
    
    def __init__(self, device_id: str, name: str):
        self.device_id = device_id
        self.name = name
        self.state = DeviceState.OFF
        self.temperature = 24.0
        self.mode = "cool"
        self.fan_speed = "auto"
    
    def turn_on(self) -> None:
        self.state = DeviceState.ON
        print(f"❄️ {self.name} 已开启")
    
    def turn_off(self) -> None:
        self.state = DeviceState.OFF
        print(f"❄️ {self.name} 已关闭")
    
    def set_temperature(self, temp: float) -> None:
        self.temperature = max(16, min(30, temp))
        print(f"❄️ {self.name} 温度: {self.temperature}°C")
    
    def set_mode(self, mode: str) -> None:
        self.mode = mode
        print(f"❄️ {self.name} 模式: {mode}")
    
    def get_status(self) -> DeviceStatus:
        return DeviceStatus(
            device_id=self.device_id,
            device_name=self.name,
            device_type=DeviceType.AIR_CONDITIONER,
            state=self.state,
            properties={
                "temperature": self.temperature,
                "mode": self.mode,
                "fan_speed": self.fan_speed
            }
        )


class TV:
    """电视设备"""
    
    def __init__(self, device_id: str, name: str):
        self.device_id = device_id
        self.name = name
        self.state = DeviceState.OFF
        self.channel = 1
        self.volume = 30
        self.source = "hdmi1"
    
    def turn_on(self) -> None:
        self.state = DeviceState.ON
        print(f"📺 {self.name} 已开启")
    
    def turn_off(self) -> None:
        self.state = DeviceState.OFF
        print(f"📺 {self.name} 已关闭")
    
    def set_channel(self, channel: int) -> None:
        self.channel = channel
        print(f"📺 {self.name} 频道: {channel}")
    
    def set_volume(self, volume: int) -> None:
        self.volume = max(0, min(100, volume))
        print(f"📺 {self.name} 音量: {self.volume}")
    
    def get_status(self) -> DeviceStatus:
        return DeviceStatus(
            device_id=self.device_id,
            device_name=self.name,
            device_type=DeviceType.TV,
            state=self.state,
            properties={
                "channel": self.channel,
                "volume": self.volume,
                "source": self.source
            }
        )


class Curtain:
    """窗帘设备"""
    
    def __init__(self, device_id: str, name: str):
        self.device_id = device_id
        self.name = name
        self.state = DeviceState.OFF
        self.position = 0
    
    def open(self) -> None:
        self.state = DeviceState.ON
        self.position = 100
        print(f"🪟 {self.name} 已打开")
    
    def close(self) -> None:
        self.state = DeviceState.OFF
        self.position = 0
        print(f"🪟 {self.name} 已关闭")
    
    def set_position(self, position: int) -> None:
        self.position = max(0, min(100, position))
        print(f"🪟 {self.name} 位置: {self.position}%")
    
    def get_status(self) -> DeviceStatus:
        return DeviceStatus(
            device_id=self.device_id,
            device_name=self.name,
            device_type=DeviceType.CURTAIN,
            state=self.state,
            properties={"position": self.position}
        )


class Speaker:
    """音响设备"""
    
    def __init__(self, device_id: str, name: str):
        self.device_id = device_id
        self.name = name
        self.state = DeviceState.OFF
        self.volume = 50
        self.playing = False
    
    def turn_on(self) -> None:
        self.state = DeviceState.ON
        print(f"🔊 {self.name} 已开启")
    
    def turn_off(self) -> None:
        self.state = DeviceState.OFF
        self.playing = False
        print(f"🔊 {self.name} 已关闭")
    
    def play(self) -> None:
        self.playing = True
        print(f"🔊 {self.name} 开始播放")
    
    def pause(self) -> None:
        self.playing = False
        print(f"🔊 {self.name} 已暂停")
    
    def set_volume(self, volume: int) -> None:
        self.volume = max(0, min(100, volume))
        print(f"🔊 {self.name} 音量: {self.volume}")
    
    def get_status(self) -> DeviceStatus:
        return DeviceStatus(
            device_id=self.device_id,
            device_name=self.name,
            device_type=DeviceType.SPEAKER,
            state=self.state,
            properties={
                "volume": self.volume,
                "playing": self.playing
            }
        )


@dataclass
class Scene:
    """场景配置"""
    name: str
    description: str
    actions: List[Callable] = field(default_factory=list)


class SmartHomeFacade:
    """智能家居外观 - 统一控制接口"""
    
    def __init__(self):
        self._devices: Dict[str, Any] = {}
        self._scenes: Dict[str, Scene] = {}
        self._schedules: List[Dict[str, Any]] = []
        self._initialize_devices()
        self._initialize_scenes()
    
    def _initialize_devices(self) -> None:
        self._devices["living_light"] = Light("light_001", "客厅灯")
        self._devices["bedroom_light"] = Light("light_002", "卧室灯")
        self._devices["study_light"] = Light("light_003", "书房灯")
        self._devices["living_ac"] = AirConditioner("ac_001", "客厅空调")
        self._devices["bedroom_ac"] = AirConditioner("ac_002", "卧室空调")
        self._devices["living_tv"] = TV("tv_001", "客厅电视")
        self._devices["living_curtain"] = Curtain("curtain_001", "客厅窗帘")
        self._devices["bedroom_curtain"] = Curtain("curtain_002", "卧室窗帘")
        self._devices["living_speaker"] = Speaker("speaker_001", "客厅音响")
    
    def _initialize_scenes(self) -> None:
        self._scenes["morning"] = Scene(
            name="晨间模式",
            description="起床模式,打开窗帘,调节温度"
        )
        self._scenes["movie"] = Scene(
            name="观影模式",
            description="关闭窗帘,调暗灯光,打开电视"
        )
        self._scenes["sleep"] = Scene(
            name="睡眠模式",
            description="关闭所有设备,调节空调温度"
        )
        self._scenes["leave"] = Scene(
            name="离家模式",
            description="关闭所有设备"
        )
        self._scenes["reading"] = Scene(
            name="阅读模式",
            description="调节灯光,关闭电视"
        )
    
    def morning_mode(self) -> None:
        """晨间模式"""
        print("\n🌅 晨间模式启动")
        self._devices["living_curtain"].open()
        self._devices["bedroom_curtain"].open()
        self._devices["living_light"].turn_off()
        self._devices["bedroom_light"].turn_off()
        self._devices["living_ac"].turn_on()
        self._devices["living_ac"].set_temperature(24)
        self._devices["living_ac"].set_mode("cool")
    
    def movie_mode(self) -> None:
        """观影模式"""
        print("\n🎬 观影模式启动")
        self._devices["living_curtain"].close()
        self._devices["living_light"].turn_on()
        self._devices["living_light"].set_brightness(10)
        self._devices["living_tv"].turn_on()
        self._devices["living_ac"].turn_on()
        self._devices["living_ac"].set_temperature(22)
        self._devices["living_speaker"].turn_on()
        self._devices["living_speaker"].set_volume(40)
    
    def sleep_mode(self) -> None:
        """睡眠模式"""
        print("\n🌙 睡眠模式启动")
        self._devices["living_light"].turn_off()
        self._devices["bedroom_light"].turn_off()
        self._devices["study_light"].turn_off()
        self._devices["living_tv"].turn_off()
        self._devices["living_speaker"].turn_off()
        self._devices["living_curtain"].close()
        self._devices["bedroom_curtain"].close()
        self._devices["bedroom_ac"].turn_on()
        self._devices["bedroom_ac"].set_temperature(26)
        self._devices["bedroom_ac"].set_mode("sleep")
    
    def leave_home_mode(self) -> None:
        """离家模式"""
        print("\n🚪 离家模式启动")
        for device in self._devices.values():
            if hasattr(device, 'turn_off'):
                device.turn_off()
    
    def reading_mode(self) -> None:
        """阅读模式"""
        print("\n📖 阅读模式启动")
        self._devices["living_tv"].turn_off()
        self._devices["living_speaker"].turn_off()
        self._devices["study_light"].turn_on()
        self._devices["study_light"].set_brightness(80)
        self._devices["study_light"].set_color("#FFF5E6")
        self._devices["living_curtain"].close()
    
    def all_lights_on(self) -> None:
        """所有灯开启"""
        print("\n💡 开启所有灯光")
        for key, device in self._devices.items():
            if isinstance(device, Light):
                device.turn_on()
    
    def all_lights_off(self) -> None:
        """所有灯关闭"""
        print("\n💡 关闭所有灯光")
        for key, device in self._devices.items():
            if isinstance(device, Light):
                device.turn_off()
    
    def set_temperature(self, temp: float) -> None:
        """设置所有空调温度"""
        print(f"\n🌡️ 设置温度: {temp}°C")
        for device in self._devices.values():
            if isinstance(device, AirConditioner):
                device.set_temperature(temp)
    
    def get_device_status(self, device_id: str) -> Optional[DeviceStatus]:
        """获取设备状态"""
        device = self._devices.get(device_id)
        if device and hasattr(device, 'get_status'):
            return device.get_status()
        return None
    
    def get_all_status(self) -> List[DeviceStatus]:
        """获取所有设备状态"""
        statuses = []
        for device in self._devices.values():
            if hasattr(device, 'get_status'):
                statuses.append(device.get_status())
        return statuses
    
    def get_scene_info(self, scene_name: str) -> Optional[Scene]:
        """获取场景信息"""
        return self._scenes.get(scene_name)
    
    def list_scenes(self) -> List[str]:
        """列出所有场景"""
        return list(self._scenes.keys())
    
    def execute_scene(self, scene_name: str) -> bool:
        """执行场景"""
        scene_methods = {
            "morning": self.morning_mode,
            "movie": self.movie_mode,
            "sleep": self.sleep_mode,
            "leave": self.leave_home_mode,
            "reading": self.reading_mode,
        }
        
        method = scene_methods.get(scene_name)
        if method:
            method()
            return True
        return False
    
    def create_custom_scene(
        self, 
        name: str, 
        actions: List[Dict[str, Any]]
    ) -> None:
        """创建自定义场景"""
        print(f"创建自定义场景: {name}")
        self._scenes[name] = Scene(
            name=name,
            description="自定义场景",
            actions=[]
        )
    
    def export_status(self) -> str:
        """导出状态为JSON"""
        statuses = self.get_all_status()
        data = {
            "timestamp": datetime.now().isoformat(),
            "devices": [
                {
                    "device_id": s.device_id,
                    "device_name": s.device_name,
                    "device_type": s.device_type.value,
                    "state": s.state.value,
                    "properties": s.properties
                }
                for s in statuses
            ]
        }
        return json.dumps(data, ensure_ascii=False, indent=2)


if __name__ == "__main__":
    home = SmartHomeFacade()
    
    home.morning_mode()
    
    home.movie_mode()
    
    home.sleep_mode()
    
    home.leave_home_mode()
    
    print("\n=== 设备状态 ===")
    for status in home.get_all_status():
        print(f"{status.device_name}: {status.state.value}")
    
    print(f"\n=== 可用场景 ===")
    for scene_name in home.list_scenes():
        scene = home.get_scene_info(scene_name)
        print(f"- {scene.name}: {scene.description}")
    
    print(f"\n=== 导出状态 ===")
    print(home.export_status())

10.5 企业级应用示例 ​

10.5.1 微服务API网关外观 ​

python
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Callable
from enum import Enum
from datetime import datetime
import json
import hashlib


class HTTPMethod(Enum):
    GET = "GET"
    POST = "POST"
    PUT = "PUT"
    DELETE = "DELETE"
    PATCH = "PATCH"


@dataclass
class APIRequest:
    path: str
    method: HTTPMethod
    headers: Dict[str, str] = field(default_factory=dict)
    params: Dict[str, str] = field(default_factory=dict)
    body: Any = None
    user_id: Optional[str] = None


@dataclass
class APIResponse:
    status_code: int
    body: Any
    headers: Dict[str, str] = field(default_factory=dict)
    execution_time: float = 0.0


class UserService:
    """用户服务"""
    
    def get_user(self, user_id: str) -> Dict[str, Any]:
        return {
            "id": user_id,
            "name": "张三",
            "email": "zhangsan@example.com",
            "role": "admin"
        }
    
    def create_user(self, data: Dict[str, Any]) -> Dict[str, Any]:
        return {"id": "user_001", **data}
    
    def update_user(self, user_id: str, data: Dict[str, Any]) -> Dict[str, Any]:
        return {"id": user_id, **data}
    
    def delete_user(self, user_id: str) -> bool:
        return True


class ProductService:
    """产品服务"""
    
    def get_products(self, params: Dict[str, str]) -> List[Dict[str, Any]]:
        return [
            {"id": "prod_001", "name": "Python教程", "price": 99.0},
            {"id": "prod_002", "name": "设计模式书籍", "price": 128.0},
        ]
    
    def get_product(self, product_id: str) -> Dict[str, Any]:
        return {"id": product_id, "name": "示例产品", "price": 99.0}
    
    def create_product(self, data: Dict[str, Any]) -> Dict[str, Any]:
        return {"id": "prod_new", **data}


class OrderService:
    """订单服务"""
    
    def get_orders(self, user_id: str) -> List[Dict[str, Any]]:
        return [
            {"id": "order_001", "user_id": user_id, "total": 198.0},
            {"id": "order_002", "user_id": user_id, "total": 256.0},
        ]
    
    def create_order(self, data: Dict[str, Any]) -> Dict[str, Any]:
        return {"id": "order_new", **data}
    
    def get_order(self, order_id: str) -> Dict[str, Any]:
        return {"id": order_id, "status": "pending"}


class PaymentService:
    """支付服务"""
    
    def process_payment(self, order_id: str, amount: float) -> Dict[str, Any]:
        return {
            "transaction_id": "txn_001",
            "order_id": order_id,
            "amount": amount,
            "status": "completed"
        }
    
    def get_payment(self, transaction_id: str) -> Dict[str, Any]:
        return {"transaction_id": transaction_id, "status": "completed"}


class NotificationService:
    """通知服务"""
    
    def send_notification(
        self, 
        user_id: str, 
        message: str
    ) -> Dict[str, Any]:
        return {
            "notification_id": "notif_001",
            "user_id": user_id,
            "message": message,
            "sent_at": datetime.now().isoformat()
        }


class CacheService:
    """缓存服务"""
    
    def __init__(self):
        self._cache: Dict[str, Any] = {}
    
    def get(self, key: str) -> Optional[Any]:
        return self._cache.get(key)
    
    def set(self, key: str, value: Any, ttl: int = 300) -> None:
        self._cache[key] = value
    
    def delete(self, key: str) -> None:
        self._cache.pop(key, None)


class AuthService:
    """认证服务"""
    
    def __init__(self):
        self._tokens: Dict[str, str] = {}
    
    def validate_token(self, token: str) -> Optional[str]:
        if token.startswith("valid_"):
            return token.replace("valid_", "user_")
        return None
    
    def generate_token(self, user_id: str) -> str:
        token = f"valid_{user_id}"
        self._tokens[token] = user_id
        return token


class RateLimiter:
    """限流器"""
    
    def __init__(self, max_requests: int = 100, window: int = 60):
        self._max_requests = max_requests
        self._window = window
        self._requests: Dict[str, List[float]] = {}
    
    def is_allowed(self, client_id: str) -> bool:
        import time
        current = time.time()
        
        if client_id not in self._requests:
            self._requests[client_id] = []
        
        self._requests[client_id] = [
            t for t in self._requests[client_id]
            if current - t < self._window
        ]
        
        if len(self._requests[client_id]) >= self._max_requests:
            return False
        
        self._requests[client_id].append(current)
        return True


class APIGatewayFacade:
    """API网关外观 - 统一微服务访问"""
    
    def __init__(self):
        self._user_service = UserService()
        self._product_service = ProductService()
        self._order_service = OrderService()
        self._payment_service = PaymentService()
        self._notification_service = NotificationService()
        self._cache = CacheService()
        self._auth = AuthService()
        self._rate_limiter = RateLimiter()
    
    def handle_request(self, request: APIRequest) -> APIResponse:
        """处理API请求"""
        import time
        start_time = time.time()
        
        try:
            if not self._rate_limiter.is_allowed(request.user_id or "anonymous"):
                return APIResponse(
                    status_code=429,
                    body={"error": "请求过于频繁"}
                )
            
            if not request.path.startswith("/auth"):
                user_id = self._authenticate(request)
                if not user_id:
                    return APIResponse(
                        status_code=401,
                        body={"error": "未授权"}
                    )
                request.user_id = user_id
            
            response_body = self._route_request(request)
            
            return APIResponse(
                status_code=200,
                body=response_body,
                execution_time=time.time() - start_time
            )
        except Exception as e:
            return APIResponse(
                status_code=500,
                body={"error": str(e)},
                execution_time=time.time() - start_time
            )
    
    def _authenticate(self, request: APIRequest) -> Optional[str]:
        token = request.headers.get("Authorization", "")
        if token.startswith("Bearer "):
            token = token[7:]
        return self._auth.validate_token(token)
    
    def _route_request(self, request: APIRequest) -> Any:
        path_parts = request.path.strip("/").split("/")
        resource = path_parts[0] if path_parts else ""
        
        if resource == "users":
            return self._handle_users(request, path_parts)
        elif resource == "products":
            return self._handle_products(request, path_parts)
        elif resource == "orders":
            return self._handle_orders(request, path_parts)
        elif resource == "auth":
            return self._handle_auth(request)
        else:
            raise ValueError(f"未知资源: {resource}")
    
    def _handle_users(self, request: APIRequest, path_parts: List[str]) -> Any:
        if len(path_parts) > 1:
            user_id = path_parts[1]
            if request.method == HTTPMethod.GET:
                return self._user_service.get_user(user_id)
            elif request.method == HTTPMethod.PUT:
                return self._user_service.update_user(user_id, request.body)
            elif request.method == HTTPMethod.DELETE:
                return {"success": self._user_service.delete_user(user_id)}
        else:
            if request.method == HTTPMethod.POST:
                return self._user_service.create_user(request.body)
        raise ValueError("无效的用户请求")
    
    def _handle_products(self, request: APIRequest, path_parts: List[str]) -> Any:
        if len(path_parts) > 1:
            product_id = path_parts[1]
            return self._product_service.get_product(product_id)
        else:
            return self._product_service.get_products(request.params)
    
    def _handle_orders(self, request: APIRequest, path_parts: List[str]) -> Any:
        if len(path_parts) > 1:
            order_id = path_parts[1]
            return self._order_service.get_order(order_id)
        else:
            if request.method == HTTPMethod.GET:
                return self._order_service.get_orders(request.user_id)
            elif request.method == HTTPMethod.POST:
                order = self._order_service.create_order(request.body)
                payment = self._payment_service.process_payment(
                    order["id"],
                    request.body.get("amount", 0)
                )
                self._notification_service.send_notification(
                    request.user_id,
                    f"订单 {order['id']} 已创建"
                )
                return {"order": order, "payment": payment}
        raise ValueError("无效的订单请求")
    
    def _handle_auth(self, request: APIRequest) -> Any:
        if request.method == HTTPMethod.POST:
            user_id = request.body.get("user_id", "anonymous")
            token = self._auth.generate_token(user_id)
            return {"token": token}
        raise ValueError("无效的认证请求")
    
    def get_user_with_orders(self, user_id: str) -> Dict[str, Any]:
        """聚合查询 - 用户及其订单"""
        user = self._user_service.get_user(user_id)
        orders = self._order_service.get_orders(user_id)
        return {"user": user, "orders": orders}
    
    def create_order_with_payment(
        self, 
        user_id: str, 
        items: List[Dict], 
        amount: float
    ) -> Dict[str, Any]:
        """创建订单并处理支付"""
        order = self._order_service.create_order({
            "user_id": user_id,
            "items": items,
            "amount": amount
        })
        
        payment = self._payment_service.process_payment(order["id"], amount)
        
        self._notification_service.send_notification(
            user_id,
            f"订单 {order['id']} 创建成功,支付金额: ¥{amount}"
        )
        
        return {"order": order, "payment": payment}


if __name__ == "__main__":
    gateway = APIGatewayFacade()
    
    print("=== 获取用户 ===")
    request = APIRequest(
        path="/users/user_001",
        method=HTTPMethod.GET,
        headers={"Authorization": "Bearer valid_user_001"}
    )
    response = gateway.handle_request(request)
    print(f"状态码: {response.status_code}")
    print(f"响应: {response.body}")
    
    print("\n=== 获取产品列表 ===")
    request = APIRequest(
        path="/products",
        method=HTTPMethod.GET,
        headers={"Authorization": "Bearer valid_user_001"},
        params={"category": "books"}
    )
    response = gateway.handle_request(request)
    print(f"产品列表: {response.body}")
    
    print("\n=== 创建订单 ===")
    request = APIRequest(
        path="/orders",
        method=HTTPMethod.POST,
        headers={"Authorization": "Bearer valid_user_001"},
        body={
            "items": [{"product_id": "prod_001", "quantity": 2}],
            "amount": 198.0
        }
    )
    response = gateway.handle_request(request)
    print(f"订单结果: {response.body}")
    
    print("\n=== 聚合查询 ===")
    result = gateway.get_user_with_orders("user_001")
    print(f"用户及订单: {result}")

10.6 模式变体与扩展 ​

10.6.1 多层外观 ​

python
from typing import Any, Dict, Optional

class SubsystemA:
    def operation(self) -> str:
        return "SubsystemA"

class SubsystemB:
    def operation(self) -> str:
        return "SubsystemB"

class LowLevelFacade:
    """底层外观"""
    
    def __init__(self):
        self._subsystem_a = SubsystemA()
        self._subsystem_b = SubsystemB()
    
    def low_operation(self) -> str:
        return f"Low: {self._subsystem_a.operation()} + {self._subsystem_b.operation()}"

class SubsystemC:
    def operation(self) -> str:
        return "SubsystemC"

class HighLevelFacade:
    """高层外观 - 组合底层外观"""
    
    def __init__(self):
        self._low_facade = LowLevelFacade()
        self._subsystem_c = SubsystemC()
    
    def high_operation(self) -> str:
        low_result = self._low_facade.low_operation()
        return f"High: {low_result} + {self._subsystem_c.operation()}"

10.6.2 外观工厂 ​

python
from typing import Any, Dict, Type, TypeVar

T = TypeVar('T')

class FacadeFactory:
    """外观工厂"""
    
    _instances: Dict[str, Any] = {}
    
    @classmethod
    def get_facade(cls, facade_type: Type[T], name: str = "default") -> T:
        key = f"{facade_type.__name__}:{name}"
        if key not in cls._instances:
            cls._instances[key] = facade_type()
        return cls._instances[key]
    
    @classmethod
    def clear_all(cls) -> None:
        cls._instances.clear()

10.6.3 动态外观 ​

python
from typing import Any, Dict, Callable

class DynamicFacade:
    """动态外观 - 运行时注册操作"""
    
    def __init__(self):
        self._operations: Dict[str, Callable] = {}
        self._subsystems: Dict[str, Any] = {}
    
    def register_subsystem(self, name: str, subsystem: Any) -> None:
        self._subsystems[name] = subsystem
    
    def register_operation(self, name: str, handler: Callable) -> None:
        self._operations[name] = handler
    
    def __getattr__(self, name: str) -> Any:
        if name in self._operations:
            return self._operations[name]
        raise AttributeError(f"未知操作: {name}")

10.7 反模式与最佳实践 ​

10.7.1 常见反模式 ​

反模式1:上帝外观 ​

python
class GodFacade:
    """上帝外观 - 承担过多职责"""
    
    def __init__(self):
        self._db = Database()
        self._cache = Cache()
        self._logger = Logger()
        self._email = EmailService()
        self._sms = SMSService()
        self._payment = PaymentService()
        self._shipping = ShippingService()
        self._inventory = InventoryService()
        self._loyalty = LoyaltyService()
        self._analytics = AnalyticsService()
    
    def do_everything(self) -> None:
        pass

解决方案:拆分为多个专注的外观类。

反模式2:外观膨胀 ​

python
class BloatedFacade:
    """外观膨胀 - 暴露过多方法"""
    
    def method_1(self): pass
    def method_2(self): pass
    def method_3(self): pass
    def method_50(self): pass

解决方案:保持外观接口简洁,仅暴露常用操作。

10.7.2 最佳实践 ​

实践描述示例
单一职责每个外观专注一个子系统OrderFacade, UserFacade
接口简洁仅暴露必要的操作高层业务方法
不限制访问允许客户端直接访问子系统子系统保持public
分层设计使用多层外观组织复杂度LowLevelFacade, HighLevelFacade
依赖注入通过构造函数注入子系统__init__(self, subsystem_a, subsystem_b)

10.8 模式比较 ​

10.8.1 与相关模式对比 ​

模式意图结构关键区别
外观简化子系统访问单向委托不改变子系统接口
适配器接口转换单向包装改变接口以兼容
装饰器动态添加职责链式包装增强功能
代理控制对象访问代理访问关注访问控制
中介者协调对象交互集中协调消除对象间直接引用

10.8.2 外观模式在架构中的位置 ​

┌─────────────────────────────────────────────────────────────┐
│                        表现层                                │
│                    (Web/Mobile/API)                         │
└───────────────────────────────────┬─────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────┐
│                        外观层                                │
│                    (Facade Layer)                           │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │ OrderFacade │  │ UserFacade  │  │ProductFacade│         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
└───────────────────────────────────┬─────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────┐
│                        业务层                                │
│                    (Business Layer)                         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │OrderService │  │UserService  │  │ProductService│        │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
└───────────────────────────────────┬─────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────┐
│                        数据层                                │
│                    (Data Layer)                             │
└─────────────────────────────────────────────────────────────┘

10.9 决策指南 ​

10.9.1 适用场景检查清单 ​

  • [ ] 需要为复杂子系统提供简单接口
  • [ ] 客户端与子系统之间存在大量依赖
  • [ ] 需要对子系统进行分层
  • [ ] 需要封装第三方库的复杂性
  • [ ] 希望遵循迪米特法则

10.9.2 实现选择决策树 ​

                    需要简化什么?
                    /          \
              整个系统         特定子系统
                /                \
        多层外观           单一外观
           /  \                  /        \
      高层外观  底层外观     可配置外观    简单外观

10.9.3 快速参考卡 ​

┌─────────────────────────────────────────────────────────────┐
│                    外观模式快速参考                          │
├─────────────────────────────────────────────────────────────┤
│ 定义: 为子系统提供统一高层接口,简化访问                      │
├─────────────────────────────────────────────────────────────┤
│ 参与者:                                                     │
│   • Facade      - 简化接口,委托子系统操作                   │
│   • Subsystem   - 实现专业功能                              │
│   • Client      - 通过外观访问子系统                        │
├─────────────────────────────────────────────────────────────┤
│ 形式化: Facade → ⋃ᵢ Oᵢ (操作组合)                          │
├─────────────────────────────────────────────────────────────┤
│ 设计原则:                                                   │
│   • 迪米特法则 (LoD)                                        │
│   • 单一职责原则 (SRP)                                      │
│   • 接口隔离原则 (ISP)                                      │
├─────────────────────────────────────────────────────────────┤
│ 典型应用:                                                   │
│   • API网关                                                 │
│   • 数据库访问层                                            │
│   • 第三方库封装                                            │
│   • 复杂系统简化                                            │
├─────────────────────────────────────────────────────────────┤
│ 最佳实践:                                                   │
│   • 保持接口简洁                                            │
│   • 不限制子系统直接访问                                    │
│   • 使用依赖注入                                            │
│   • 避免上帝外观                                            │
└─────────────────────────────────────────────────────────────┘

10.10 小结 ​

外观模式是简化复杂系统接口的有效方式。其核心价值在于:

  1. 简化接口:为复杂子系统提供简单易用的入口
  2. 降低耦合:客户端与子系统解耦,遵循迪米特法则
  3. 分层设计:支持系统的层次化组织
  4. 灵活访问:不限制客户端直接访问子系统

在Python中,外观模式常用于封装第三方库、简化API调用、构建分层架构。在微服务架构中,API网关是外观模式的现代演进,为分布式系统提供统一的访问入口。


思考与练习 ​

  1. 基础练习:为一个文件操作库(读写、压缩、加密)设计外观模式。

  2. 进阶练习:实现一个支持插件扩展的外观模式,允许动态注册新的子系统。

  3. 挑战练习:设计一个多层外观系统,支持从底层到高层的渐进式简化。

  4. 设计思考:外观模式与API网关有何关系?请分析其演进过程。

Python技术丛书 - 江苏省宿城中等专业学校