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

时间:2011-09-28 20:18:21

标签: oop associations cardinality

我最近一直在考虑面向对象的主体/实践/范例,例如SOLID,Demeter法和DDD,并且一个不断出现的主题是强制执行对象基数。

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

我想知道的是:如果业务领域需要严格的基数模型,那么执行它的最佳方法是什么?我能想到的技术包括以下内容:

  • 双向引用 - 关联对象之间的双向关联(对象A引用对象B,对象B引用对象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;
      }
    }
    
  • 封装拥有的实体 - 让所有者控制其创建和删除,并通过一组抽象实际实体实现的API提供访问权限(对象A克隆传入实体B或根据传递的原理图创建实体B

    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));
      }
    }
    
  • 第三方监视器 - 让一些了解基数约束的第三方创建并正确连接对象关联(对象C知道A和B之间的关系,并负责创建和维护它 - 此方法仅适用于C且不可供客户使用)

    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 :(得分:0)

建立协会不是任何一个班级的责任。将其留给调解员来创建链接。

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