MCP(Model-Controller-Provider模式)是对传统MVC模式的改进版本,更适合现代应用开发。这种分层架构使得代码结构清晰,便于维护和扩展,同时也提高了代码的可测试性和可重用性。每一层都有其明确的职责,通过依赖注入的方式来管理它们之间的关系,使得系统更加灵活和可维护。

    Model:数据模型层,定义数据结构和业务实体Controller:控制层,处理用户输入并协调Model和ProviderProvider:提供者层,负责数据访问和业务逻辑的实现

主要优势:

    解耦:各层职责明确,相互独立可测试:每层都可以独立测试可维护:修改某一层不影响其他层可扩展:易于添加新功能和修改现有功能依赖清晰:通过依赖注入管理组件关系

以一个电商系统的订单管理模块为例,详细说明MCP (Model-Controller-Provider)模式的应用:

    整体架构关系图:
┌─────────────────┐
│    HTTP请求     │
└────────┬────────┘
         ↓
┌─────────────────┐
│  路由配置层     │     路由将请求映射到对应的Controller方法
│  (Routes)       │
└────────┬────────┘
         ↓
┌─────────────────┐
│  控制器层       │     处理HTTP请求/响应,参数验证,调用Provider
│  (Controller)   │
└────────┬────────┘
         ↓
┌─────────────────┐
│  提供者层       │     实现核心业务逻辑,操作Model
│  (Provider)     │
└────────┬────────┘
         ↓
┌─────────────────┐
│  模型层         │     定义数据结构和实体关系
│  (Model)        │
└─────────────────┘
    数据流向和依赖关系:
// 1. Model层是基础,被其他层引用
interface Order {
    id: string;
    items: OrderItem[];
    // ...其他属性
}

// 2. Provider层依赖Model层,实现业务逻辑
class OrderProvider {
    // 使用Model定义的数据结构
    async createOrder(data: Order): Promise<Order> {
        // 业务逻辑实现
    }
}

// 3. Controller层依赖Provider层,处理HTTP请求
class OrderController {
    constructor(
        private orderProvider: OrderProvider // 依赖注入
    ) {}

    async createOrder(req: Request, res: Response) {
        // 调用Provider层的方法
        const order = await this.orderProvider.createOrder(req.body);
        res.json(order);
    }
}

// 4. 依赖注入层组装各个组件
class OrderModule {
    static configure() {
        // 创建Provider实例
        const provider = new OrderProvider();
        // 注入Provider到Controller
        const controller = new OrderController(provider);
        return { controller };
    }
}

// 5. 路由配置层连接HTTP请求和Controller
function configureRoutes(app: Express) {
    const { controller } = OrderModule.configure();
    app.post('/orders', controller.createOrder.bind(controller));
}
    Model层被所有其他层引用,定义数据结构和类型,但不依赖其他层,其数据模型定义是:
// models/order.model.ts
export interface OrderItem {
    productId: string;
    quantity: number;
    price: number;
}

export interface Order {
    id: string;
    userId: string;
    items: OrderItem[];
    totalAmount: number;
    status: OrderStatus;
    createdAt: Date;
    updatedAt: Date;
}

export enum OrderStatus {
    PENDING = 'PENDING',
    PAID = 'PAID',
    SHIPPED = 'SHIPPED',
    DELIVERED = 'DELIVERED',
    CANCELLED = 'CANCELLED'
}
    Provider层依赖Model层,被Controller层调用,用于实现核心业务逻辑,其业务逻辑实现是:
// providers/order.provider.ts
export class OrderProvider {
    constructor(
        private readonly orderRepository: OrderRepository,
        private readonly inventoryProvider: InventoryProvider,
        private readonly paymentProvider: PaymentProvider
    ) {}

    async createOrder(userId: string, items: OrderItem[]): Promise<Order> {
        // 检查库存
        await this.checkInventory(items);
        
        // 计算总金额
        const totalAmount = this.calculateTotal(items);
        
        // 创建订单
        const order = {
            userId,
            items,
            totalAmount,
            status: OrderStatus.PENDING,
            createdAt: new Date(),
            updatedAt: new Date()
        };
        
        return this.orderRepository.save(order);
    }

    async payOrder(orderId: string, paymentMethod: string): Promise<Order> {
        const order = await this.orderRepository.findById(orderId);
        
        // 处理支付
        await this.paymentProvider.processPayment({
            orderId,
            amount: order.totalAmount,
            method: paymentMethod
        });

        // 更新订单状态
        order.status = OrderStatus.PAID;
        order.updatedAt = new Date();
        
        return this.orderRepository.update(order);
    }

    private async checkInventory(items: OrderItem[]): Promise<void> {
        for (const item of items) {
            const available = await this.inventoryProvider.checkStock(item.productId);
            if (available < item.quantity) {
                throw new Error(`Insufficient stock for product ${item.productId}`);
            }
        }
    }

    private calculateTotal(items: OrderItem[]): number {
        return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
    }
}
    Controller层依赖Provider层,被路由配置调用处理HTTP请求/响应,其请求处理和响应是:
// controllers/order.controller.ts
export class OrderController {
    constructor(private readonly orderProvider: OrderProvider) {}

    async createOrder(req: Request, res: Response) {
        try {
            const { userId, items } = req.body;
            
            // 输入验证
            this.validateCreateOrderInput(userId, items);
            
            // 调用Provider创建订单
            const order = await this.orderProvider.createOrder(userId, items);
            
            // 返回成功响应
            res.status(201).json({
                success: true,
                data: order
            });
        } catch (error) {
            // 错误处理
            res.status(400).json({
                success: false,
                error: error.message
            });
        }
    }

    async payOrder(req: Request, res: Response) {
        try {
            const { orderId, paymentMethod } = req.body;
            
            // 处理支付
            const updatedOrder = await this.orderProvider.payOrder(
                orderId, 
                paymentMethod
            );
            
            res.status(200).json({
                success: true,
                data: updatedOrder
            });
        } catch (error) {
            res.status(400).json({
                success: false,
                error: error.message
            });
        }
    }

    private validateCreateOrderInput(userId: string, items: OrderItem[]) {
        if (!userId) throw new Error('User ID is required');
        if (!items || items.length === 0) throw new Error('Order items are required');
        // 更多验证逻辑...
    }
}
    依赖注入和模块组装,用于创建和组装其他层的实例,管理依赖关系,提供模块化配置:

用组装电脑的例子来解释依赖注入的三个核心概念:

  • 创建和组装其他层的实例,就像电脑组装店:
    • 首先需要采购各种零件:主板、CPU、内存、硬盘等
    • 然后按照正确的顺序把这些零件组装到一起
    • 确保每个零件都是兼容的,能够正常工作
    • 最终组装成一台完整的电脑
  • 管理依赖关系,就像电脑零件之间的连接关系:
    • CPU必须安装在主板的CPU插槽上
    • 内存必须插在主板的内存插槽上
    • 显卡需要插在主板的PCIe插槽上
    • 每个零件都有其特定的连接方式和依赖关系
  • 提供模块化配置,就像根据不同用户需求配置电脑:
    • 游戏玩家需要高性能显卡和大容量内存
    • 办公用户可能只需要集成显卡和普通内存
    • 设计师需要专业显卡和大容量存储
    • 可以根据预算和需求灵活调整配置

实际应用的好处:

  • 灵活替换
    • 就像CPU坏了可以直接更换新的
    • 不需要更换其他正常工作的零件
    • 只要接口兼容,可以随时升级零件
  • 便于维护
    • 每个零件都是独立的模块
    • 出现问题容易定位是哪个零件的问题
    • 维修或更换时不会影响其他零件
  • 标准化
    • 所有零件都遵循统一的接口标准
    • 不同厂商的零件可以互相兼容
    • 组装过程有标准的步骤和流程
  • 可扩展性
    • 需要更多功能时可以添加新的零件
    • 可以根据需求升级某些零件
    • 系统容易扩展和升级

总结来说,依赖注入就像是一个专业的电脑组装工厂:

  • 负责准备和组装所有需要的零件(创建实例)
  • 确保零件之间正确连接(管理依赖)
  • 根据不同需求提供不同配置(模块化配置)

这种方式让系统像组装电脑一样模块化,容易维护,也更容易根据需求进行调整和升级。

// modules/order.module.ts
export class OrderModule {
    static configure() {
        const orderRepository = new OrderRepository();
        const inventoryProvider = new InventoryProvider();
        const paymentProvider = new PaymentProvider();
        
        const orderProvider = new OrderProvider(
            orderRepository,
            inventoryProvider,
            paymentProvider
        );
        
        const orderController = new OrderController(orderProvider);
        
        return { orderController };
    }
}
    路由配置依赖Controller层,映射URL到Controller方法,是应用的入口点:
// routes/order.routes.ts
export function configureOrderRoutes(app: Express) {
    const { orderController } = OrderModule.configure();
    
    app.post('/api/orders', orderController.createOrder.bind(orderController));
    app.post('/api/orders/:id/pay', orderController.payOrder.bind(orderController));
}