2009-08-10 24 views
6

私は最近、ツリー構造、複数のノード、複数のレベルと増加可能なレベル、print()メソッドを扱っています。まず が、私はそれがコンポジットであるべきと思った、私はその後、いくつかの可能な設計とコードを書いた:コンポジットパターンは、ちょうどアレイに私をもたらすのでしょうか?

alt text

$struc = new Node(‘name0’, ‘id0’, ‘desc0’); 
$node1 = new Node(‘node1’, ‘id1’, ‘desc1’); 
$node2 = new Node(‘node2’, ‘id2’, ‘desc2’); 
$node3 = new Node(‘node3’, ‘id3’, ‘desc3’); 
$leaf1 = new Leaf(‘leaf1’, ‘ld1’, ‘lesc1’); 
$leaf2 = new Leaf(‘leaf2’, ‘ld2’, ‘lesc2’); 
$leaf3 = new Leaf(‘leaf3’, ‘ld3’, ‘lesc3’); 
$leaf4 = new Leaf(‘leaf4’, ‘ld4’, ‘lesc4’); 

$struc.add($node1); 
$struc.add($node3); 

$node1.add($leaf1); 
$node1.add($leaf2); 
$node1.add($node2); 

$node2.add($leaf3);  
$node3.add($leaf4); 

がよさそうだ、私は考え、コーディング、印刷()メソッドを開始するIteratorに従うことができます後でパターン。 しかし、コーディング中、私はこれらの単純なノードでは複雑すぎると感じていますか?そして、私は具体的なクラスをたくさんインスタンス化しなければなりません(50以上の、そして増加しています)。私はこのパターンの重要な何かを逃しています、Compositeパターンの価値は何だ、今私は少し混乱している、2つのデザインは非常によく似て

-- Structure Class -- 
//To be more readable and clear, array here could be 
//divided to 3 arrays(root/nodes/leafs), then connect 
//in a similar way Composite does. 
$struc = array('name0', 'id0', 'desc0', 

      'children'=>array(

       array('node1', 'id1', 'desc1', 
        'children' => array(
        array('leaf1', 'ld1', 'lesc1'), 
        array('leaf2', 'ld2', 'lesc2'), 
        array('node2', 'id2', 'desc2', 
         'children'=>array(array('leaf3', 'ld3', 'lesc3')) 
        ) 
       ) 
       ), 

       array('node3', 'id3', 'desc3', 
        'children' => array(array('leaf4', 'ld4', 'lesc4')) 
       ) 
      ) 
); 

function print($node = $this->struct) { 
    ... 
    if(isset($node['children'])) $this->print($node['children']); 
    ... 
} 

:私は、配列を使って、簡単な同様の方法を考えて停止し、 ?

+2

私の結論:デザインパターンは素晴らしいですが、常に好むわけではありません。この例では、ツリーに1000以上のノードがあると仮定すると、Compositeの実装ではクライアントが1000以上のオブジェクトをインスタンス化する必要があります。パフォーマンスを向上させ、リソースを節約するために、Flyweightという別のパターンに対処する必要があります。プログラムはますます複雑になり、最後にComposite + Iterator + Flyweight(+ Vistor)が実装されます。配列と1つのメソッドを持つ1つのクラスで解決できる単純な問題について。最後に、この質問では、私の答えは、配列の実装は、パターンの実装を破るです。 – Edward

答えて

6

composite patternのポイントは、オブジェクトの集合をあたかも単一オブジェクト(あたかもそれを表示またはファイルに書き込む)のように扱うことができることです。 "print()メソッドは後でIteratorパターンに従うかもしれません" - 複合パターンのポイントは、単一のComponentを印刷しているかどうかを心配することなくprint()を呼び出すことができるということです。木全体を通して

しかし、ネストされた配列を代わりに使用することを検討しているので、一般的にオブジェクト指向プログラミングについてはっきりしていないように見えます。すべてのためにハッシュ(PHP配列である)の代わりにオブジェクトを使用することの価値は、type safetyです。これは、プログラムのデバッグと保守をはるかに簡単にします。

+0

私は長い間、Oのプログラミングでは、私は彼らが重要であることを知っているので、私は多くの原則とパターンに従って、長い時間Cプログラマーでした。私の理解では、OOは主にプログラムを変更しやすいように維持する方法ですが、通常はわかりませんし、効果があるかどうかもわかりません。この例では、例えば、私はまだコンポジットが提供するはずの低価格を見て、ノードを追加/削除し、順序を変更することはできません。 – Edward

+0

このように考えてみましょう。オブジェクトの代わりに配列を使用するのは、すべてのメソッドパラメータにvoid *を使用するCプログラムに似ています。 –

+0

私はあなたの考え方が違うと感じ、Array実装について考えます。私はそれがOO実装であると思いますが、Compositeではないと思いますか? 私はあなたが言った例を理解することができますが、配列の代わりにオブジェクトを使用して理解するのは助けにはなりません。この例では、利点はありますか? – Edward

7

コンポジットの価値は、のカプセル化を破ることができないように、ある程度の複雑さを払うことです。です。複合と

if(isset($node['children'])) $this->print($node['children']); 

は、あなたが言うことができます:実行時ポリモーフィズム、その後

print(); 

ノードが葉ではない場合、あなたが テストであるため、ご使用のアレイバージョンで

あなたはカプセル化を壊しています正しい方法を呼び出すでしょう。この場合、(私はPHPプログラマじゃないので、私は、Javaに似た構文を使用するようにしましょう):

class Node { 

    void print() { 
     for (child in children) { 
      child.print(); 
     } 
    } 

    ... 
} 

class Leaf { 

    void print() { 
     // print it! 
    } 
} 

無地のアレイを介して別の利点は、あなたの実装の詳細(データ構造などを隠しているということです)

+0

私は理解しようとしましたが、まだ精神をキャッチすることはできません。以下は私の考えです、私の間違いを指摘すること自由に感じ、私もコード内のいくつかの間違いを修正しました。 1. "カプセル化を中断する"、私は混乱していますが、エンティティとしてノードを扱っていないのですが、それでもカプセル化が破られていますか?そしてそれはどんな問題を引き起こすでしょうか? 2.実装の詳細がクラス構造に隠れていると思いますが、そうではありませんか? 3.コンポジットの利点はまだわかりません。このツリーをどのように変更しても、コード変更の価格は2つの方法で同じように見えます。 – Edward

+0

コードが良く見えるようになりました。1.コンポジットを使用すると、リーフの操作とノードの操作が区別されません。2.配列がクラスにカプセル化されていることは明らかです。あなたのオリジナルの質問ではありません – dfa

0

配列の実装がもっと複​​雑に見えませんか?私がそれを見ているなら、私はあなたがしていることを理解するためにそれをもっと勉強しなければなりません。あなたはインデックスを扱っている、特定のインデックスなどにエントリを割り当てる...それは本当に複雑に見えます。

他のサイトでのコンポジットパターンの実装は、使用しているコードを見ているとシンプルで自然に見えます。あなたはノードを持っていて、それに他のノードやリーフを付けます。複雑で奇妙なものは何もありません。索引などを気にしたり覚えたりする必要はありません。そういうわけで、複合パターンがあなたの場合に役立つのです。もちろん、あなたがそれに慣れていなければ、その実装は少し複雑に見えるかもしれませんが、重要な点は、あなたが詳細を隠しているということです。これは、非常にです。これは簡単な例ですが、配列でも動作しますが、他の開発者がコードを編集/維持している実稼働環境でこのようなコードを実装すると、誰かが "配列"ソリューションを変更する必要がある場合、新しいバグを導入する可能性がはるかに高いです。

+0

私は以前のコードでいくつかの間違いを修正しました。 – Edward

関連する問題