GRASP之控制器模式 - Kamil Grzybek

banq發表於2019-09-05

問題:UI層之外的第一個物件是否接收並協調“控制”系統操作?
解決方案:將責任分配給表示以下選項之一的物件:
  • - 表示整個“系統”,“根物件”,執行軟體的裝置或主要子系統(這些都是外觀控制器的變體)
  • -表示發生系統操作的用例場景(用例或會話控制器)

這個原則實現取決於我們系統的高階設計,但一般我們需要定義協調我們的業務事務處理的物件。乍一看,似乎Web應用程式/ API中的MVC控制器在這裡是一個很好的例子(即使名稱是相同的)但對我來說並非如此。當然它接收輸入但它不應該協調系統操作 - 它應該將它委託給單獨的服務或命令處理程式:

public class CustomerOrdersController : Controller
{
    private readonly IMediator _mediator;

    public CustomerOrdersController(IMediator mediator)
    {
        this._mediator = mediator;
    }

    /// <summary>
    /// Add customer order.
    /// </summary>
    /// <param name="customerId">Customer ID.</param>
    /// <param name="request">Products list.</param>
    [Route("{customerId}/orders")]
    [HttpPost]
    [ProducesResponseType((int)HttpStatusCode.Created)]
    public async Task<IActionResult> AddCustomerOrder(
        [FromRoute]Guid customerId, 
        [FromBody]CustomerOrderRequest request)
    {
       await _mediator.Send(new AddCustomerOrderCommand(customerId, request.Products));

       return Created(string.Empty, null);
    }
}

public class AddCustomerOrderCommandHandler : IRequestHandler<AddCustomerOrderCommand>
{
    private readonly ICustomerRepository _customerRepository;
    private readonly IProductRepository _productRepository;
    private readonly IForeignExchange _foreignExchange;

    public AddCustomerOrderCommandHandler(
        ICustomerRepository customerRepository, 
        IProductRepository productRepository, 
        IForeignExchange foreignExchange)
    {
        this._customerRepository = customerRepository;
        this._productRepository = productRepository;
        this._foreignExchange = foreignExchange;
    }

    public async Task<Unit> Handle(AddCustomerOrderCommand request, CancellationToken cancellationToken)
    {
        // handling...
    }
}


 

相關文章