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

Oop 强制对象关联基数的模式和实践,oop,associations,cardinality,Oop,Associations,Cardinality,我最近一直在思考面向对象的原则/实践/范例,如SOLID、Law of Demeter和DDD,一个不断浮出水面的主题是强化对象基数 对象关联基数源自业务规则,这些规则要求某些实体只能与一定数量的其他实体对象关联。例如,如果您正在设计一个管理仓库的系统,那么业务规则可能是单个项目只能存储在一个仓库中。显然,在软件设计中实施这些规则是一个实现问题 我想知道的是:如果业务领域需要一个严格的基数模型,那么实施它的最佳方式是什么?我可以马上想到的技术包括: 双向引用-关联对象之间的双向关联(对象A引用

我最近一直在思考面向对象的原则/实践/范例,如SOLID、Law of Demeter和DDD,一个不断浮出水面的主题是强化对象基数

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

我想知道的是:如果业务领域需要一个严格的基数模型,那么实施它的最佳方式是什么?我可以马上想到的技术包括:

  • 双向引用-关联对象之间的双向关联(对象A引用对象B,对象B引用对象A)

    类仓库{
    私人清单项目;
    公共无效登记项目(项目obj){
    如果(对象仓库!=null)
    抛出新ArgumentException(“只能注册未拥有的项”)
    项目。添加(obj);
    对象仓库=此;
    }
    }
    
  • 封装所属实体-让所有者控制其创建和删除,并通过一组抽象实际实体实现的API提供访问(对象a克隆实体B中传递的a或根据传递的原理图创建实体B)

    类仓库{
    私人清单项目;
    公共无效登记项目(项目obj){
    items.Add((Item)obj.Clone());
    }
    公共无效注册表项(ItemDescriptor项){
    项目。添加(新项目(项目));
    }
    }
    
  • 第三方监视器-让一些了解基数约束的第三方适当地创建和连接对象关联(对象C了解A和B之间的关系,并负责创建和维护它-此方法仅对C可用,对客户端不可用)

    类仓库{
    私人清单项目;
    内部无效登记项目(项目obj){
    项目。添加(obj);
    }          
    }
    类别WarehouseItemRegistrationService{
    私人名单登记处;
    公共作废登记项目(仓库、项目){
    if(注册数据项包含(项))
    抛出新ArgumentException(“只能注册未拥有的项目”);
    仓库登记项目(项目);
    }
    }
    
我认为每种技术都有它的优点和缺点。双向关联会增加对象图的复杂性,并需要私有API来更新引用,但实现和嵌入业务实体类中的业务约束非常简单。封装所拥有的实体可以通过强制实体具有基于值的描述使域模型复杂化,但它非常干净。第三方监控技术将显式基数强制隔离到单独的类中,但它也使域模型复杂化


有人有其他想法、想法或更好的方法吗?

建立联系不是任何一个阶层的责任。将其留给中介来创建链接


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

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


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

这也可以通过服务类完成,而不需要由谁负责建立关系,但不需要额外的类WarehouseItem。对于WarehouseItem,您必须保护构造函数不被WarehouseItemFactory使用,对于服务,您必须保护用于关联实例的属性不被服务使用。所以我想我的观点是,创建另一个类和一个用于创建它的工厂并不能从我所看到的东西中买到很多东西,而且服务可能更简单。当然。重要的一点是,关联是由一个类建立的,该类对
仓库和
项目都有概述,并了解其规则。这也可以通过一个服务类来实现,而不需要由谁负责建立关系,但不需要额外的类WarehouseItem。对于WarehouseItem,您必须保护构造函数不被WarehouseItemFactory使用,对于服务,您必须保护用于关联实例的属性不被服务使用。所以我想我的观点是,创建另一个类和一个用于创建它的工厂并不能从我所看到的东西中买到很多东西,而且服务可能更简单。当然。重要的一点是,关联是由一个类建立的,该类对
仓库
和“Item”都有概述,并了解其规则。
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;
  }
}
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));
  }
}
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);
  }
}