2012-02-08 4 views
2

私はJavaで動作しますデコレーターパターン - 一度に2種類を飾る方法

私はグラフエッジのデコレータの素敵な構造を作成しました。私は2つの頂点を持つベースエッジを持っている、私はエッジに重みを追加する加重デコレータを持っているし、私はエッジに方向を追加する方向付けされたデコレータを持っています。デコレータは、継承ではなく、インタフェースとデリゲートメソッドを使用して実装されます。

ここで、フローエッジに対応する別のデコレータ、つまりフローデコレータを追加したいと思います。フローエッジは、方向と重量(容量)とフローの両方を持ちます。このようなJavaの実装方法を教えてください。

public class FlowEdge implements IEdge, IWeightedEdge, IOrientedEdge, IFlowEdge 
{ 
    private IEdge, IWeightedEdge, IOrientedEdge decorated; 
    private int flow; 

    //constructors, delegate methods... 

などが必要ですが、それは明らかに不可能です。

おそらく、デコレータは使用するのに最適なパターンではありません。私は懸念の分離を達成したいと思います(私は正常な、重み付けされた、指向エッジの任意の組み合わせを持つことができます)が、1つのクラスの多分複数のデコレータの機能が必要です。これは何とか可能ですか?それとも私はこれを工学的に工夫していますか?

+2

なぜ「これは明らかに不可能ですか? 1つのクラスだけを 'extend 'することはできますが、任意の数のインタフェースを' implement'することができます。 –

+0

私は行を意味しました プライベートIEdge、IWeightedEdge、IOrientedEdge装飾; すべての型を保持するために、デリゲートメソッドを実装する必要があります。 –

+1

@JakubZaverkaはい、そうです。 –

答えて

0

私はこの全体のデコレータのアイデアを手放すと普通inheritaceのようなエッジを実装しました。

エッジ - > WeightedEdge - > OrientedEdge - > FlowEdge

それは多分装飾を使用してのようにエレガントではないと私は今、非加重指向のエッジを持つことはできませんが、それは単純で簡単です。

1

デコレータは、継承によって ではなくインターフェイスとデリゲートメソッドを使用して実装されています。

私はこれがあなたが壁に乗っている理由だと思います。デコレータパターンは、継承と多型を使用することで、Javaできれいになります。これは「言語対プログラミング」の「プログラミング」の良い例です。

+0

どのように2つのデコレータで1つのクラスを飾るのですか?私はJavaの2つのクラスから継承することはできません。 –

+1

これは、デコレータがJavaでどのように動作するかを正確には示していません。あなたはあなたと同じくらい継承しません。実行時に飾ります。たとえば、新しいBufferedReader(新しいFileReader( "readme.txt"))。 –

1

デザインに欠陥があると思われます。デコレータは通常、デコレートするクラスを「ラップ」し、そのコンストラクタに渡されます。あなたのコードは、次のようなものにする必要があります:

Graph myGraph = new BaseGraph(); 
Graph decoratedGraph = new FlowedGraph(new WeightedGraph(new OrientedGraph(myGraph))); 
+0

ありがとうございました...はい、私はそれを教えたようにデコレータです。しかし、FlowedGraphは方向と重量の両方を持っていなければなりません。この場合、 "decoree"が両方になることは保証できません。私はそれを重み付けまたは指向性にすることができます。 –

0

デコレータが実装する装飾の種類を間違えているようです。デコレータが飾っているものを正確に知ることは間違っているようです。他のデコレータクラスに依存する「複合デコレータ」を実装して、それ自体が提供する新しい動作に加えて特定の動作を追加することができます。おそらく、このような何か:

public class FlowEdge implements IEdge // or IFlowEdge 
{ 
    private IEdge decorated; 
    private int flow; 

    public FlowEdge(IEdge decorated) { 
     this.decorated = new WeightedEdge(new OrientedEdge(decorated)); 
     . . . 
    } 
} 
+0

興味深い考えですが、コンストラクタで渡すことができないので、重みと方向の任意の値を持たなければなりません(型をチェックしてから適切な型にキャストする)。 –

+0

@JakubZaverka - 関連するプロパティをコンストラクタで渡すことができないのはなぜですか?あなたが記述したところから、 'FlowEdge'プロパティには' WeightedEdge'と 'OrientedEdge'のすべてのプロパティが含まれます。これらは、 'FlowEdge'コンストラクタ内の関連するコンストラクタに渡すことができます。 (おそらく私は何かを誤解しているので、なぜタイプチェックとキャストが必要なのかわかりません) –

+0

'FlowEdge(WeightedEdge wedge、OrientedEdge oedge)'私はこの道をしばらくしていましたが、あなたは2つの異なるインスタンスを渡すことができます。 'if(wedge!= oedge)'をチェックしてから何らかの例外をスローする必要があります。それはすでに実行時になっており、コンパイル時にチェックしておきたいと思います。 –

関連する問題