複合パターンを使用するか、ツリー構造を使用するか、3番目の実装を使用するかをどのように判断できますか?


14

オブザーバー」タイプと「サブジェクト」タイプの2つのクライアントタイプがあります。それらは両方ともグループの階層に関連付けられています

オブザーバーは、異なる階層全体で関連付けられているグループから(カレンダー)データを受信します。このデータは、データを収集しようとしているグループの「親」グループからのデータを組み合わせて計算されます(各グループは1つの親のみを持つことができます)。

サブジェクトは、関連付けられているグループにデータ(オブザーバーが受信するデータ)を作成できます。グループでデータが作成されると、グループのすべての「子供」もデータを持ち、データの特定の領域の独自のバージョンを作成できますが、作成された元のデータにリンクされます(私の特定の実装では、元のデータには期間と見出しが含まれますが、サブグループは、それぞれのグループに直接リンクされた受信者の残りのデータを指定します)。

ただし、サブジェクトがデータを作成するとき、影響を受けるすべてのオブザーバーがこれと競合するデータを持っているかどうかを確認する必要があります。つまり、理解できる限り、巨大な再帰関数を意味します。

したがって、これは、上下に移動できる階層を持たせる必要があるという事実に要約できると思います、いくつかの場所はそれらを全体として扱うことができます(基本的に再帰)。

また、私は単に機能するソリューションを目指しているわけではありません。比較的理解しやすく(少なくともアーキテクチャ的には)、将来的に追加機能を簡単に受信できる柔軟性を備えたソリューションを見つけたいと思っています。

この問題または同様の階層の問題を解決するための設計パターン、または実行すべき優れたプラクティスはありますか?

編集

私が持っているデザインは次のとおりです。 メソッドを含むクラス図。 「グループ」クラスは階層です

「Phoenix」クラスは、適切な名前をまだ考えていなかったため、そのように命名されています。

しかし、これに加えて、グループを通じて特定のオブザーバーに関連付けられている場合でも、特定のオブザーバーに対して特定のアクティビティ非表示にする必要があります。


少しオフトピック

個人的には、この問題をより小さな問題に切り詰めることができるはずだと感じていますが、それは私をどのように回避します。相互に関連付けられていない複数の再帰機能と、さまざまな方法で情報を取得する必要があるさまざまなクライアントタイプが関係しているためだと思います。本当に頭を包むことはできません。階層の問題をカプセル化する方法を改善する方向に誰かが私を導くことができれば、それを受け取ることも非常にうれしいです。


これはグラフ理論の問題のように聞こえます。したがって、グループの階層を表すいくつかの有向グラフがあります。各グループはグラフの頂点です。どのプロパティが当てはまりますか?入次数nが0の一意の頂点が常に存在し、他のすべての頂点には最低1の入次数があるのは本当ですか?すべての頂点が接続されていnますか?n一意のパスはありますか?データ構造のプロパティを一覧表示し、その操作をインターフェイス(メソッドのリスト)に抽象化できる場合、私たち(I)はそのデータ構造の実装を考え出すことができます。

ご回答ありがとうございます。オブザーバーを介した場合を除き、互いに接続されていないグループの複数の階層がありますが、それらはグラフオブジェクトの一部ではなく、単に頂点へのリンクがあるだけです。階層内の各グループは、親を1つだけ持つことができますが、子は0 .. *です。それをグラフにどのように実装しますか?そして、1つのグループが入っている階層のみが0の入次数を持ちます。2グループ階層以上の場合、それらはすべて少なくとも1の等しい入出次数を持ちます。関連するメソッドをリストしてみます。仕事中の1時間で。

したがって、グループはC#のサブクラス化のように機能しますか。1つの基本クラスをサブクラス化できますが、フォレスト(つまり、互いに素なツリー)があります。すべてのポインタ/参照を接続すると、暗黙的にグラフが作成されます。すでに他に何もする必要はありません。ただし、「これらの2つのグループは同じ階層にありますか?」「これら2つのグループの共通の祖先は何ですか?」構造について事前に知っているすべてのことを活用するために、体系的に分析された問題が必要です。

あなたの図を見ましたので、あなたの質問は正確に何ですか-それが設​​計アプローチに関するものである場合、私はさまざまな設計方法論に慣れていないので、現時点ではあなたを本当に助けることはできません。しかし、O(n)明確に定義されたデータ構造のための効率的なアルゴリズムを探しているなら、私はそれに取り組むことができます。変異メソッドGroupや階層構造は一切追加しなかったようです。これらは静的であると仮定しますか?

1
@Malachi答えが見つかりませんでした。残念ながら、私はそれを完全に調査する時間がなく、他の何かに移らなければなりませんでした。私は今それを調べる時間もありませんが、時々通知をチェックすることを確認します-そして誰かが実行可能な良い答えを出したら、それを受け入れます。
アスケ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

ご使用のシステムの使用要件または実装要件については限られた見方しかありませんが、具体的に説明するのは困難です。たとえば、考慮されるものは次のとおりです。

  • システムは非常に同時(多くのユーザー)ですか?
  • データアクセスの読み取り/書き込み比率はどのくらいですか?(高読み取り、低書き込みが一般的です)

パターンなどに関しては、ソリューションでどのような正確なパターンが現れるかについてはあまり気にせず、実際のソリューションの設計についてはもっと心配します。デザインパターンの知識は役立つと思いますが、すべてではありません。作家のアナロジーを使用すると、デザインパターンは、本全体を書かなければならない文の辞書というよりも、よく見られるフレーズの辞書のようなものです。から。

あなたの図は一般的に私には問題ないように見えます。

あなたが言及していないメカニズムが1つあり、それは何らかのキャッシュを持っています階層内にです。明らかにこれを細心の注意を払って実装する必要がありますが、システムのパフォーマンスが大幅に向上する可能性があります。以下に簡単な説明を示します(注意事項)。

階層内の各ノードについて、継承されたデータをノードに保存します。これを遅延的または積極的に行いますが、それはあなた次第です。階層が更新されると、影響を受けるすべてのノードのキャッシュデータを再生成してから、または適切な場所にセット「汚い」フラグをし、必要ないい加減に再生成された影響を受けたデータを持っています。

これがあなたのシステムでどれほど適切かはわかりませんが、検討する価値があるかもしれません。

また、SOに関するこの質問は関連する場合があります。

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


0

私はこれが一種の明白であることを知っていますが、とにかく言うつもりです、あなたはObserver Pattern あなたがオブザーバータイプを持っていること、そしてあなたが私にとってオブザーバーパターンのように見えるものを言ったことを見てみるべきだと思います。

いくつかのリンク:

DoFactory

oodesign

それらをチェックしてください。それ以外の場合は、ダイアグラムにあるものをコーディングし、必要に応じてデザインパターンを使用して単純化します。あなたはすでに何が起こる必要があり、プログラムがどのように機能するかを知っています。いくつかのコードを書き、それがまだ収まるかどうかを確認します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.