コンポジットデザインパターンを見る

私はナショナル・パブリック・ラジオのを聞いていた他の日の車の話、発信者が自分の車についての質問を、その間の人気毎週放送。すべてのプログラムが中断する前に、ショーのホストは発信者に1-800-CAR-TALK(1-800-227-8255に対応)をダイヤルするように要求します。もちろん、前者は後者よりもはるかに覚えやすいことがわかります。これは、「CAR TALK」という単語が複合語であるためです。つまり、7桁を表す2つの単語です。人間は一般に、個々のコンポーネントよりもコンポジットを扱う方が簡単だと感じています。同様に、オブジェクト指向ソフトウェアを開発する場合、個々のコンポーネントを操作するのと同じようにコンポジットを操作すると便利なことがよくあります。その前提は、コンポジットデザインパターンの基本原則を表しています。このJavaデザインパターンのトピック 取り付け。

複合パターン

複合パターンに飛び込む前に、まず複合オブジェクトを定義する必要があります。他のオブジェクトを含むオブジェクト。たとえば、図面は、線、円、長方形、テキストなどのグラフィックプリミティブで構成されている場合があります。

Java開発者は、プリミティブオブジェクトを操作するのとまったく同じ方法でコンポジットを操作する必要があるため、コンポジットパターンが必要です。たとえば、線やテキストなどのグラフィックプリミティブは、描画、移動、およびサイズ変更する必要があります。ただし、これらのプリミティブで構成される図面などのコンポジットに対しても同じ操作を実行する必要があります。理想的には、プリミティブオブジェクトとコンポジットの両方に対して、2つを区別せずに、まったく同じ方法で操作を実行する必要がありますプリミティブオブジェクトとコンポジットを区別して、これら2つのタイプのオブジェクトに対して同じ操作を実行する必要がある場合、コードはより複雑になり、実装、保守、および拡張がより困難になります。

デザインパターン、著者はこのようなCompositeパターンを説明します。

オブジェクトをツリー構造に構成して、部分全体の階層を表します。コンポジットを使用すると、クライアントは個々のオブジェクトとオブジェクトの構成を均一に扱うことができます。

複合パターンの実装は簡単です。複合クラスは、プリミティブオブジェクトを表す基本クラスを拡張します。図1は、複合パターンの構造を示すクラス図を示しています。

図1のクラス図では、デザインパターンの複合パターンの説明にあるクラス名を使用しComponentました。プリミティブオブジェクトの基本クラス(または場合によってはインターフェイス)をComposite表し、複合クラスを表します。たとえば、Componentクラスはグラフィックプリミティブの基本クラスを表す場合がありますが、Compositeクラスはクラスを表す場合がありDrawingます。図1のLeafクラスは、具体的なプリミティブオブジェクトを表しています。たとえば、LineクラスまたはTextクラス。Operation1()そしてOperation2()方法は両方によって実装ドメイン固有の方法表現Component及びCompositeクラスを。

Compositeこのクラスは、コンポーネントのコレクションを維持します。通常、Compositeメソッドは、そのコレクションを反復処理し、コレクションComponent内のそれぞれに適切なメソッドを呼び出すことによって実装されます。たとえば、Drawingクラスは次のdraw()ようにメソッドを実装できます。

//このメソッドは複合メソッドですpublicvoid draw(){//コンポーネントを反復処理しますfor(int i = 0; i <getComponentCount(); ++ i){//コンポーネントへの参照を取得し、その描画を呼び出しますメソッドコンポーネントコンポーネント= getComponent(i); component.draw(); }}

Componentクラスに実装されているすべてのメソッドについて、クラスは、上記Compositedraw()メソッドで示されているように、コンポジットのコンポーネントを反復処理するのと同じシグネチャを持つメソッドを実装します。

Compositeクラスが延びComponentコンポーネントを期待するメソッドに複合体を渡すことができるように、クラス、たとえば、次の方法を検討してください。

//このメソッドは、// ComponentクラスとCompositeクラスに関係のないクラスに実装されますpublicvoid repaint(Component component){//コンポーネントはコンポジットにすることができますが、// Componentクラスを拡張するため、このメソッドは必要ありません。 //コンポーネントとコンポジットを区別しますcomponent.draw(); }

上記のメソッドには、単純なコンポーネントまたは複合のいずれかのコンポーネントが渡され、そのコンポーネントのdraw()メソッドが呼び出されます。ので、Compositeクラスが延びComponentrepaint()この方法は、構成要素と区別する必要はなく、複合材料、それは単に呼び出すdraw()コンポーネント(または複合)する方法。

図1の複合パターンクラス図は、パターンに関する1つの問題を示しています。を参照するときにコンポーネントと複合を区別する必要Componentがあり、などの複合固有のメソッドを呼び出す必要がありますaddComponent()。通常isComposite()Componentクラスになどのメソッドを追加することで、この要件を満たします。そのメソッドはfalseコンポーネントを返し、Compositeクラスでオーバーライドされて戻りtrueます。さらに、次のようComponentに、Compositeインスタンスへの参照もキャストする必要があります。

... if(component.isComposite()){コンポジットコンポジット=(コンポジット)コンポーネント; Composite.addComponent(someComponentThatCouldBeAComposite); }..。

addComponent()メソッドにはComponent参照が渡されることに注意してください。参照は、プリミティブコンポーネントまたはコンポジットのいずれかです。そのコンポーネントはコンポジットにすることができるため、前述のDesign Patternsからの引用で示されているように、コンポーネントをツリー構造に構成できます。

図2は、代替の複合パターンの実装を示しています。

図2の複合パターンを実装する場合、コンポーネントと複合を区別する必要はなくComponentCompositeインスタンスへの参照をキャストする必要もありません。したがって、上記のコードフラグメントは1行になります。

... component.addComponent(someComponentThatCouldBeAComposite); ..。

しかし、Component前のコードフラグメントの参照がを参照していない場合はComposite、どうすればaddComponent()よいですか?これは、図2の複合パターンの実装との主要な論点です。プリミティブコンポーネントには他のコンポーネントが含まれていないため、コンポーネントを別のコンポーネントに追加しても意味がありません。そのため、Component.addComponent()メソッドはサイレントに失敗するか、例外をスローする可能性があります。通常、コンポーネントを別のプリミティブコンポーネントに追加するとエラーと見なされるため、例外をスローすることがおそらく最善のアクションです。

では、どの複合パターンの実装(図1または図2の実装)が最適ですか?これは、複合パターンの実装者の間で常に大きな議論の的となっています。コンポーネントとコンテナを区別する必要がなく、キャストを実行する必要もないため、デザインパターンは図2の実装を好みます。個人的には、図1の実装を好みます。なぜなら、そのオブジェクトタイプに意味のないクラスにメソッドを実装することに強い嫌悪感を持っているからです。

複合パターンとその実装方法を理解したところで、Apache Struts JavaServer Pages(JSP)フレームワークを使用した複合パターンの例を見てみましょう。

複合パターンとストラットタイル

Apache Strutsフレームワークには、Tilesと呼ばれるJSPタグライブラリが含まれており、複数のJSPからWebページを作成できます。Tilesは、実際にはJ2EE(Java 2 Platform、Enterprise Edition)CompositeViewパターンの実装であり、それ自体がDesign PatternsCompositeパターンに基づいています。複合パターンとタイルタグライブラリとの関連性について説明する前に、まずタイルの理論的根拠とその使用方法を確認しましょう。すでにStrutsTilesに精通している場合は、次のセクションをざっと読み、「StrutsTilesで複合パターンを使用する」から読み始めることができます。

注: J2EE CompositeViewパターンの詳細については、「コンポジットビューで簡単に作成できるWebアプリケーションコンポーネント」(JavaWorld、 2001年12月)の記事を参照してください。

設計者は、多くの場合、個別の領域のセットを使用してWebページを作成します。たとえば、図3のWebページは、サイドバー、ヘッダー、コンテンツ領域、およびフッターで構成されています。

多くの場合、Webサイトには、図3のサイドバー/ヘッダー/コンテンツ/フッターのレイアウトなど、同じレイアウトの複数のWebページが含まれています。Struts Tilesを使用すると、複数のWebページ間でコンテンツとレイアウトの両方を再利用できます。その再利用について説明する前に、図3のレイアウトが従来HTMLのみでどのように実装されているかを見てみましょう。

手作業で複雑なレイアウトを実装する

例1は、図3のWebページをHTMLで実装する方法を示しています。

例1.手作業で実装された複雑なレイアウト

    手作業による複雑なレイアウトの実装<%-1つのテーブルにこのページのすべてのコンテンツがレイアウトされます-%>
   
リンク

ホーム

製品

ダウンロード

白い紙

お問い合わせ

Sabreware、Incへようこそ。
ページ固有のコンテンツはここにあります

立ち寄ってくれてありがとう!

前述のJSPには、2つの大きな欠点があります。1つは、ページのコンテンツがJSPに埋め込まれているため、サイドバー、ヘッダー、フッターが多くのWebページで同じである可能性が高い場合でも、JSPを再利用できないことです。次に、ページのレイアウトもそのJSPに埋め込まれているため、同じWebサイト内の他の多くのWebページが同じレイアウトを使用していても、同様に再利用することはできません。次に説明するように、このアクションを使用して最初の欠点を修正できます。

JSPを使用して複雑なレイアウトを実装する

例2は、以下を使用する図3のWebページの実装を示しています