Паттерны и практики для усиления кардинальности ассоциаций объектов - PullRequest
2 голосов
/ 29 сентября 2011

В последнее время я много размышлял об объектно-ориентированных принципах / практиках / парадигмах, таких как SOLID, Law of 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 голосов
/ 19 апреля 2012

Создание ассоциаций не является обязанностью обоих классов.Оставьте это посреднику, чтобы создать ссылку.

Создайте класс ассоциации WarehouseItem для представления ассоциации и класс WarehouseItemFactory для установления ассоциаций путем создания экземпляров WarehouseItem.WarehouseItemFactory будет нести ответственность за соблюдение правил кардинальности.

...