服务层应该保持任何状态吗?或者仅通过构造函数/ setter注入?

时间:2010-01-12 18:07:19

标签: c# java asp.net-mvc

我有一个在控制器中使用的OrderService。

我所做的只是从自定义控制器继承,我将OrderService作为属性添加。我在OnActionExecuting事件中初始化OrderService。

初始化OrderService时,我设置了Order属性。

这是因为OrderService对Order执行操作,因此将其设置一次而不必将Order传递给每个方法都是有意义的。

此设计是否遵循良好做法?

public class MyController : Controller
{
      public OrderService OrderService {get; set;}

      protected override void OnActionExecuting(...)
      {
          OrderService = new OrderService(getOrderIdFromCookie());

      }
}



   public class OrderService
   {
        private Order _order;

        public OrderService(int orderId)
        {
          _order = Dao.GetOrderById(orderId);
        }


        public void AddProduct(Product product)
        { 
            product.OrderId = _order.Id;   // assumes order is loaded
            ProductDao.Add(product);
        }

   }

这实际上是一个与语言无关的问题,据我所知,服务不应该包含任何类型的任何状态。

我认为服务层类应该是单身正确吗? (使用依赖注入进行设置时)。

方法不应假设Order对象具有状态。

如果是这种情况,那么我的设计是不正确的?

4 个答案:

答案 0 :(得分:2)

服务层不应该是单身人士。

它也不应包含对象状态。

服务层应该能够在其类型的任何实例上运行,而不是存储单个实例......这导致必须创建多个服务实例以处理多个订单。例如:

public interface IOrderService
{
    public void AddProduct(Order order, Product product);
}

public class DaoOrderService : IOrderService 
{ 
    public Order GetOrder(orderId)
    {
        return Dao.GetOrderById(orderId);
    } 

    public void AddProduct(Order order, Product product) 
    {
        // The way this method works seems like it should be in a ProductService
        // rather than in the OrderService.
        product.OrderId = _order.Id;
        ProductDao.Add(product); 
    } 
}

然后你的控制器会有类似的东西:

public class MyController : Controller 
{    
    public IOrderService OrderService { get; private set; }

    public MyController(IOrderService orderService)
    {
        OrderService = orderService ?? new DaoOrderService();
    }

    public MyController()
        : this(null)
    { }

    protected override void OnActionExecuting(...) 
    {             
        Order myOrder = OrderService.GetOrder(orderId);

        // Some stuff here
        orderService.AddProduct(myOrder, selectedProduct);
    } 
} 

答案 1 :(得分:1)

市场上的大多数ORM产品采用不同的方法,我倾向于认为这是一种更好的做法,即遍历对象图持续变化。

这意味着而不是

    public void AddProduct(Product product)
    { 
        product.OrderId = _order.Id;   // assumes order is loaded
        ProductDao.Add(product);
    }

你这样做:

myOrder.Products.Add(product);
Service.Save(myOrder);

答案 2 :(得分:0)

我认为服务通常是我喜欢随时调用的一组方法。根据我的理解,服务始终存在,我不必创建一个。虽然有些用例可以通过服务工厂来实现。

所以我的观点是,服务应该是无状态的 - 至少从用户的角度来看。它可以保留一些由服务提供商维护或设置的一般状态,但从用户的角度来看,它应该像单身一样显示。

不能说它是正确还是不正确的设计,但我会避免有状态或参数化的服务(或以不同的方式调用各种类)

答案 3 :(得分:0)

你的方法在你描述的方式上有些不同寻常是正确的。

当代智慧表明“服务层”或“服务类”不保持状态 - 它将接受所有输入(包括订单)作为其API函数的参数。但是(fwiw)您的服务似乎只是一个内存中的.NET对象 - 而不是WebService或EJB或其他基于网络的服务。实际上你根本不需要把它称为“服务”。

您的对象可能是'OrderProcessor',或者甚至更好(也许),您可以将服务类与订单类本身结合起来。

我希望我能提供一个更完整的描述,以及一个可靠的推荐,但很难(对我而言)仅仅看一对接口是非常自以为是。您提到的实践模式是为了在某些情况下提供优势而创建的。如果我不知道你的情况究竟是什么,那么声称知道“正确”的答案基本上是Cargo Cult Programming