强制对象关联基数的模式和实践

3

最近我一直在思考与面向对象的原则、实践和范型有关的内容,例如SOLID、Demeter定律和DDD等。一个不断浮现的主题是强制执行对象基数。

对象关联基数源自业务规则,这些规则规定某些实体只能与一定数量的其他实体对象相关联。例如,如果您正在设计一个管理仓库的系统,一个业务规则可能是单个物品只能存储在一个仓库中。显然,在软件设计中强制执行这些规则是一个实施的问题。

我的疑问是:在业务领域需要严格的基数模型时,最好的执行方法是什么?我能想到的技术包括以下几种:

  • Bi-directional references - Bi-directional associations between associated objects (object A references object B and object B references object A)

    class Warehouse {
      private List<Item> items;
    
      public void RegisterItem(Item obj) {
        if(obj.Warehouse != null)
          throw new ArgumentException("Can only register un-owned item")
    
        items.Add(obj);
        obj.Warehouse = this;
      }
    }
    
  • Encapsulate the owned entity - let the owner control its creation and deletion and provide access through a set of APIs that abstract the actual entity implementation (object A clones a passed in entity B or creates an entity B based on a passed schematic)

    class Warehouse {
      private List<Item> items;
    
      public void RegisterItem(Item obj) {
        items.Add((Item)obj.Clone());
      }
    
      public void RegisterItem(ItemDescriptor item) {
        items.Add(new Item(item));
      }
    }
    
  • Third party monitor - Have some third party that understands cardinality constraints create and hookup object associations appropriately (object C knows about the relationship between A and B and is responsible for creating and maintaining it - this method is only available to C and not available to clients)

    class Warehouse {
      private List<Item> items;
    
      internal void RegisterItem(Item obj) {
        items.Add(obj);
      }          
    }
    
    class WarehouseItemRegistrationService {
    
      private List<Item> registeredItems;
    
      public void RegisterItem(Warehouse warehouse, Item item) {
        if(registeredItems.Contains(item))
          throw new ArgumentException("Can only register un-owned items");
    
        warehouse.RegisterItem(item);
      }
    }
    
我认为每种技术都有其长处和短处。双向关联会增加对象图的复杂性,并需要私有API来更新引用,但是它非常容易实现,并将业务约束嵌入到业务实体类中。封装所属实体会通过强制实体具有基于值的描述而使域模型变得复杂,但是非常清晰。 第三方监视器 技术将显式基数强制规定隔离到一个单独的类中,但也会使域模型变得复杂。
大家还有什么其他想法、建议或更好的方法吗?
1个回答

0

建立关联不是任何一个类的职责。将其留给中介者来创建链接。

创建一个关联类WarehouseItem,用于表示关联,并创建一个WarehouseItemFactory类来通过创建WarehouseItem的实例来建立关联。 WarehouseItemFactory 将负责强制执行基数规则。


1
这也可以通过一个服务类来完成,其责任是建立关系,但不需要额外的WarehouseItem类。使用WarehouseItem,您必须保护构造函数不被WarehouseItemFactory以外的其他方式使用,而使用服务,则必须保护用于关联实例的属性不被服务以外的其他方式使用。所以我想我的观点是,从我所看到的情况来看,创建另一个类和一个工厂并不能为您带来太多好处,而使用服务可能更简单。 - jpierson
1
当然。重要的是,该关联由一个类来建立,该类具有对WarehouseItem的概述,并了解其规则。 - user1342582

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接