Як ви можете сказати, чи слід використовувати композитний візерунок або структуру дерева, або третю реалізацію?


14

У мене є два типи клієнтів, тип " спостерігач " і " суб'єкт ". Вони обоє пов'язані з ієрархією груп .

Спостерігач отримає (календар) дані від груп, з якими він асоціюється, у різних ієрархіях. Ці дані обчислюються, комбінуючи дані з "батьківських" груп групи, яка намагається збирати дані (у кожній групі може бути лише один батьківський ).

Суб'єкт зможе створювати дані (які отримуватимуть спостерігачі) у групах, з якими вони пов’язані. Коли дані створюються в групі, всі "діти" групи також матимуть дані, і вони зможуть скласти свою власну версію певної області даних , але все ще пов'язану з вихідними даними, створеними (у в моїй конкретній реалізації, вихідні дані будуть містити часовий період (і) та заголовок, тоді як підгрупи визначають решту даних для приймачів, безпосередньо пов'язаних з їх відповідними групами).

Однак, коли Суб’єкт створює дані, він повинен перевірити, чи є у всіх постраждалих спостерігачів якісь дані, що суперечать цьому, що означає величезну рекурсивну функцію, наскільки я можу зрозуміти.

Тому я думаю, що це можна підсумувати тому, що мені потрібно мати ієрархію, за якою можна підніматися вгору і вниз , а в деяких місцях можна розглядати їх як ціле (рекурсія, в основному).

Крім того, я не просто націлений на рішення, яке працює. Я сподіваюся знайти рішення, яке є досить простим для розуміння (принаймні розумним для архітектури), а також досить гнучким, щоб мати можливість отримувати додаткові функціональні можливості в майбутньому.

Чи існує модель дизайну чи добра практика, щоб вирішити цю проблему чи подібні проблеми з ієрархією?

Редагувати :

Ось дизайн у мене: Діаграма класу з включеними методами.  Клас "Група" - це ієрархія

Клас "Фенікс" названий таким чином, тому що я ще не придумав відповідної назви.

Але крім цього мені потрібно вміти приховувати конкретні заходи для конкретних спостерігачів , навіть якщо вони приєднуються до них через групи.


Трохи поза темою :

Особисто я відчуваю, що мені слід вдаватись до того, щоб вирішити цю проблему до менших проблем, але мені це вдається уникнути. Я думаю, це тому, що він включає в себе безліч рекурсивних функцій, не пов'язаних один з одним і різними типами клієнтів, яким потрібно отримувати інформацію різними способами. Я не можу реально обернути голову навколо цього. Якщо хтось може направити мене в напрямку, як стати кращим у вирішенні проблем ієрархії, я би дуже радий отримати це.


Це звучить як проблема теорії графіків. Отже, у нас є деякий диграф, що представляє ієрархію груп. Кожна група - це вершина у графі. Які властивості справджуються? Чи правда, що завжди існує унікальна вершина nзі ступенем 0, тоді як кожна інша вершина має ступінь принаймні 1? Чи пов'язана кожна вершина n? Чи шлях до nунікального? Якщо ви зможете перерахувати властивості структури даних і віднести її операції до інтерфейсу - переліку методів - ми (I), можливо, зможемо придумати реалізацію зазначеної структури даних.

Спасибі за вашу відповідь. Існує кілька ієрархій груп, які не приєднані одна до одної, за винятком Спостережників, але я не думаю, що вони є частиною об’єктів графіків, вони просто мають посилання на вершини в них. Кожна група в ієрархії може мати лише 1 батьків, але 0 .. * дітей. Як би ти це реалізував у графі? І тільки ієрархія з 1 групою в матиме ступінь 0. Для 2-груп ієрархій і більшої вони мають однаковий ступінь і ступінь не менше 1. Спробую перерахувати відповідні методи через годину, коли я на роботі.

Тож чи працюють групи так само, як підкласифікація в C #: Ви можете підкласирувати один базовий клас, за винятком того, що є ліс (тобто нерозчленовані дерева)? Добре, якщо ви з'єднаєте всі вказівники / посилання, то неявно у вас вже є графік - вам більше нічого не потрібно робити. Річ, однак, якщо ви хочете ефективно робити операції на кшталт "Чи ці дві групи в одній ієрархії?" "Що спільного предка для цих двох груп?" і т. д. вам потрібно систематично аналізувати проблему, щоб скористатися всіма відомостями, які ви заздалегідь знаєте про структуру.

Тепер, коли я побачив вашу діаграму, в чому саме ваше питання - якщо мова йде про дизайнерський підхід, то я не можу вам реально допомогти, оскільки я сам новачок у різних методологіях проектування. Однак якщо ви шукаєте ефективні O(n)алгоритми для чітко визначеної структури даних, я можу над цим працювати. Я бачу, ви не вкладали жодних мутуючих методів Groupта структури ієрархій. Чи варто вважати, що вони будуть статичними?

1
@Malachi я не знайшов відповіді. На жаль, я не встиг повністю дослідити це і довелося перейти до чогось іншого. Я також не встигаю зараз це розглядати, але я обов’язково раз у раз перевірятиму своє сповіщення - і якщо хтось дасть хорошу життєздатну відповідь, то я прийму це.
Aske B.

Відповіді:


1

Ось проста "групова" реалізація, яка дозволяє переходити до кореня та переміщуватися до цього кореневого дерева як колекції.

public class Group
{
  public Group Parent
  public List<Group> Children

  public IEnumerable<Group> Parents()
  {
    Group result = this;
    while (result.Parent != null)
    {
      result = result.Parent;
      yield return result;
    }
  }
  public Group Root()
  {
    return Parents.LastOrDefault() ?? this;
  }


  public IEnumerable<Group> WalkTreeBreadthFirst(
  {
    //http://en.wikipedia.org/wiki/Breadth-first_search
    HashSet<Group> seenIt = new HashSet<Group>()
    Queue<Group> toVisit = new Queue<Group>();
    toVisit.Enqueue(this);

    while (toVisit.Any())
    {
      Group item = toVisit.Dequeue();
      if (!seenIt.Contains(item))
      {
        seenIt.Add(item);
        foreach (Group child in item.Children)
        {
          toVisit.Enqueue(child);
        }
        yield return item;
      }
    }
  }

  public static IEnumerable<Group> WalkTreeDepthFirst()
  {
    // http://en.wikipedia.org/wiki/Depth-first_search
    HashSet<Group> seenIt = new HashSet<Group>();
    Stack<Group> toVisit = new Stack<Group>();

    toVisit.Push(this);

    while (toVisit.Any())
    {
      Group item = toVisit.Pop();
      if (!seenIt.Contains(item))
      {
        seenIt.Add(item);
        foreach (Group child in item.Children.Reverse())
        {
          toVisit.Push(child);
        }
        yield return item;
      }
    }
  }
}

Отже - давши групу, ви можете ходити по дереву цієї групи:

Group myGroup = GetGroup();
Group root = myGroup.Root;
foreach(Group inTree in root.WalkTreeBreadthFirst())
{
  //do something with inTree Group.
}

Я сподіваюся, що виклав це, полягає в тому, що, показуючи, як орієнтуватися по дереву (і розвіяти його складність), ви можете мати уявлення про операції, які ви хочете виконати на дереві, а потім перегляньте шаблони самостійно, щоб побачити що найкраще стосується.


0

З обмеженим уявленням щодо вимог щодо використання або впровадження вашої системи важко отримати занадто конкретні. Наприклад, такі речі, які будуть враховані, можуть бути:

  • чи система є дуже одночасною (багато користувачів)?
  • яке співвідношення читання / запису доступу до даних? (часто читається, мало записується)

Що стосується шаблонів тощо, то я б менше хвилювався про те, які точні візерунки з'являються у вашому рішенні, і більше про дизайн фактичного рішення. Я думаю, що знання шаблонів дизайну є корисним, але не все-таки і все-таки: щоб використовувати аналогію письменника, дизайнерські шаблони більше схожі на словник загальноприйнятих фраз, а не словник речень, ви повинні написати цілу книгу з.

Звичайно, ваша діаграма виглядає нормально.

Є один механізм, про який ви не згадували, і це мати якийсь кеш у вашій ієрархії. Очевидно, ви повинні реалізувати це дуже обережно, але це може значно підвищити продуктивність вашої системи. Ось простий досвід цього (емптор застереження):

Для кожного вузла вашої ієрархії зберігайте успадковані дані разом із вузлом. Робіть це ліниво чи активно, це залежить від вас. Коли оновлюється ієрархія, ви можете або регенерувати дані кешу для всіх порушених вузлів там і далі, або встановити "брудні" прапори у відповідних місцях, і пошкоджені дані ліниво повторно генеруються, коли це необхідно.

Я поняття не маю, наскільки це доречно у вашій системі, але, можливо, варто задуматися.

Крім того, це питання щодо SO може бути актуальним:

/programming/1567935/how-to-do-inheritance-modeling-in-relational-databases


0

Я знаю, що це різновид очевидного, але я все одно скажу це, я думаю, ви повинні поглянути на Observer Pattern згадане вами, що у вас є тип спостерігача, і те, що у вас виглядає, схоже на мене.

пара посилань:

DoFactory

дизайн

перевірити це. в іншому випадку я б просто зашифрувати те, що є у вашій діаграмі, а потім використовувати шаблон дизайну для спрощення, якщо необхідно. ви вже знаєте, що має відбутися і як програма повинна працювати. Напишіть якийсь код і подивіться, чи він все-таки відповідає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.