web-dev-qa-db-ja.com

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

Observer "-type」と「Subject"-type」の2つのクライアントタイプがあります。どちらもグループの階層に関連付けられています。

オブザーバーは、異なる階層全体で関連付けられているグループから(calendar)dataを受け取ります。このデータは、データを収集しようとしているグループの「親」グループからのデータを結合によって計算されます(各グループは1つの親のみを持つことができます)。

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

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

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

また、私は機能するソリューションを目指しているだけではありません。比較的理解しやすく(少なくともアーキテクチャの観点から)、将来的に追加機能を簡単に受け取ることができるほど柔軟なソリューションを見つけたいと思っています。

この問題または同様の階層の問題を解決するための設計パターン、または適切な方法はありますか?

[〜#〜]編集[〜#〜]

ここに私が持っているデザインがあります: Class diagram with methods included. The "Group" class is the hierarchy

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

しかし、これに加えて、私は特定のオブザーバーの特定のアクティビティを非表示にするができる必要があります。


少しずれたトピック

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

14
Aske B.

以下は、ルートにナビゲートし、そのルートのツリーをコレクションとしてナビゲートできるようにする単純な「グループ」実装です。

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.
}

これを投稿する私の希望は、ツリーをナビゲートする方法を示す(およびその複雑さを払拭する)ことで、ツリーで実行する操作について視覚化し、自分のパターンに戻って確認できることです。何が最も当てはまるか。

1
Amy B

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

いくつかのリンク:

DoFactory

oodesign

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

0
Malachi

限られたビューでは、システムの使用法や実装の要件を把握しているため、具体的に説明するのは困難です。たとえば、次のような点が考慮されます。

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

パターンなどについては、ソリューションでどのパターンが発生するかについては心配せず、実際のソリューションの設計については心配しません。デザインパターンの知識は有用ですが、すべてではなく、すべてではありません。ライターの類推を使用すると、デザインパターンは、本全体を書く必要がある文章の辞書ではなく、一般的に見られるフレーズの辞書に似ています。から。

あなたの図は一般的に私には大丈夫に見えます。

言及していないメカニズムが1つあります。それは、階層に何らかのcacheがあることです。もちろん、これは慎重に実装する必要がありますが、システムのパフォーマンスを大幅に向上させることができます。ここにそれを簡単に取り上げます(警告エンプター):

階層内の各ノードについて、継承されたデータをノードとともに保存します。これを怠惰にまたは積極的に行います。それはあなた次第です。階層が更新されると、影響を受けるすべてのノードのキャッシュデータを再生成し、または適切な場所に「ダーティ」フラグを設定して、影響を受けるようにすることができます。データは必要に応じて遅延して再生成されます。

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

また、S.O。に関するこの質問関連があるかもしれません:

https://stackoverflow.com/questions/1567935/how-to-do-inheritance-modeling-in-relational-databases

0
occulus