您如何分辨是使用复合模式还是树结构,还是第三个实现?


14

我有两种客户端类型,即“ 观察者 ”类型和“ 主题 ”类型。它们都与层次结构相关联。

观察者将从不同层次中与其关联的组中接收(日历)数据。通过合并尝试收集数据的组的“父”组中的数据(每个组只能有一个父组)来计算此数据。

主题将能够在与其关联的组中创建数据(观察者将接收)。当在一个组中创建数据时,该组的所有“子级”也将拥有该数据,他们将能够为数据的特定区域制作自己的版本,但仍链接到创建的原始数据(在在我的特定实现中,原始数据将包含时间段和标题,而子组则为直接链接到其各自组的接收者指定其余数据。

但是,当主体创建数据时,必须检查所有受影响的观察者是否有与此冲突的数据,据我所知,这意味着庞大的递归功能。

因此,我认为这可以归纳为以下事实:我需要具有一个可以在其中上下移动的层次结构,并且某些地方必须能够将它们作为一个整体对待(基本上是递归)。

另外,我不仅针对可行的解决方案。我希望找到一种相对容易理解的解决方案(至少在体系结构方面),并且足够灵活,以便将来能够轻松接收其他功能。

是否有解决此问题或类似层次结构问题的设计模式或良好实践?

编辑

这是我的设计: 具有方法的类图。 “组”类是层次结构

“ Phoenix”类以这种方式命名,因为我还没有想到合适的名称。

但是除此之外,我需要能够为特定的观察者隐藏特定的活动,即使这些活动通过组与之相连。


有点题外话

就我个人而言,我认为我应该可以将这个问题分解为较小的问题,但这使我无所适从。我认为这是因为它涉及多个相互不关联的递归功能,以及需要以不同方式获取信息的不同客户端类型。我真的不能把头缠住它。如果有人能指导我如何更好地封装层次结构问题,我也将很高兴收到这一消息。


这听起来像一个图论问题。因此,我们有一些表示组层次结构的有向图。每个组都是图中的一个顶点。什么属性成立?是否确实总是存在一个n度数为0 的唯一顶点,而每个其他顶点的度数至少为1?每个顶点都连接到n吗?通往n独特的道路吗?如果您可以列出数据结构的属性并将其操作抽象到接口(方法列表)上,我们(I)可能能够提出所述数据结构的实现。

谢谢您的答复。除通过观察器外,有多个彼此不附加的组层次结构,但我不认为它们是图对象的一部分,它们只是具有指向顶点的链接。层次结构中的每个组只能有1个父级,但0 .. *个子级。您将如何在图中实现它?而且只有具有1个群组的层次结构的入度为0。对于2个群组层次结构及更大的层次结构,它们的入度和出度均相等,至少为1。我将尝试列出其相关方法一个小时内,当我在工作时。

那么这些组的工作方式就像在C#中的子类化一样:您可以子类化一个基类,但有一个森林(即,不相交的树)除外?好吧,如果您连接了所有的指针/引用,那么就已经隐含了一个图形-您无需执行任何其他操作。但是,如果要有效地执行“这两个组是否在同一层次结构中?”之类的操作,那就是。“这两个群体的共同祖先是什么?” 等等。您需要对问题进行系统地分析,以利用您事先了解的有关结构的所有知识。

既然我已经看到了您的图表,那么您到底要问什么-如果是关于设计方法的,那么,由于我本人是各种设计方法的新手,因此我目前无法真正为您提供帮助。但是,如果您正在寻找有效的O(n)算法来定义明确的数据结构,那么我可以解决这个问题。我看到您没有Group在层次结构上添加任何变异方法。我是否可以假设这些是静态的?

1
@Malachi我没有找到答案。不幸的是,我没有时间去充分研究它,不得不继续前进。我现在也没有时间研究它,但是我将确保每隔一段时间检查一次我的通知-如果有人给出了一个可行的答案,那么我会接受的。
Aske B.

Answers:


1

这是一个简单的“组”实现,可让您导航到Root,并将该Root的树作为集合进行导航。

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 您提到的您有一个Observer类型,对我而言,您看起来像是Observer模式。

几个链接:

DoFactory

设计

检查那些。否则,我只会对图表中的内容进行编码,然后在必要时使用设计模式进行简化。您已经知道需要发生什么以及该程序应该如何工作。编写一些代码,看看它是否仍然适合。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.