OO にはかなり慣れていないので、単純化された例から与えられた実際の要件に移行しようとするまでは、概念を理解していると感じることがよくあります。この特定の問題について考える方法を理解する助けをいただければ幸いです。
コンテナとそれに入るアイテムを定義するパネルを持つ GUI があります。現在、コンテナには 3 つのタイプがあります。コンテナーにはいくつかのプロパティ (サイズなど) があり、1 ~ 3 種類のアイテムを含めることができます (2 つはオプション)。十分な情報が入力されたら、その情報を使用してグラフを作成します。
Observer パターンを実装しました。ユーザーが情報を入力すると、observable が更新され、変更されたことをグラフに通知します。
私は今のところ幸せです。今、しわ。私のコンテナにはサイズがありますが、明示的に入力されることもあれば、コンテナが保持しているものによって決定されることもあります。それはコンテナの種類によって決まります。明示的に入力されていない場合、サイズの決定方法は、オプションの項目の 1 つがコンテナー内にあるかどうかによって異なります。要件作成者が私を嫌っているだけなのか、それとも十分なオブジェクト指向の経験が不足しているのかはわかりませんが、それらのしわが私にフィットしています。現在、オブザーバブルには、さまざまな情報をすべて保持するための変数があり、特殊なケースを処理するために一連の switch ステートメントを使用しています。
ビルダーパターンを使用できると考えています。ディレクターは、グラフ化されたデータを作成します。コンテナーの種類ごとに具体的なビルダーを用意し、コンテナーのプロパティとその中の項目を使用してクラスをインスタンス化します。getContainerSize() など、グラフに必要な値をディレクタに返し、これらを組み合わせて実際のデータ ポイントを生成する抽象ビルダー クラスのメソッドを用意します。また、ユーザーがまだグラフを完成させるのに十分なデータを入力していない場合、director は null を返す可能性があります。
使用可能な OO 設計に近づいていますか? 特別なケーシングをもう少し深く埋めただけではないかどうかはわかりません.
シワがもう一つ。アイテム タイプの 1 つは、3 つのコンテナすべてに入っています。現在、私のオブザーバブルはコンテナーとアイテムを別々に追跡し、グラフを作成するメソッドが何を求めるかを決定します (ユーザーが値をいじると、グラフは大きく変化します)。複数のビルダー パターンがある場合、どのように機能しますか?
多分私はステップを逃していますか?オブザーバブルは現在のコンテナのビルダーを更新し、その座標を取得するためにディレクターを呼び出す必要があることをグラフに知らせますか? 次に、現在のコンテナが何であるかを尋ねる必要があるのはどれですか?
オブジェクト指向の設計や特にこの問題について理解するのに役立つすべてのコメントを歓迎します。実際の要件にはさらに特殊なケースがありますが、この基本的なテーマのバリエーションです。
返信ありがとうございます。私は、2 つの質問を混ぜ合わせて罪を犯していると思います。ここでは、Builder パターンに焦点を当てた最小限のコード例を提供しようとしています。IE8 に注意してください。FireFox 8 ではありません。IE8 でコードを読んでいる人には申し訳ありません。
interface MyContainerBuilder
{
void setContents( MyContents contents );
Double myVolume();
Double myDensity();
}
class SmallContainerBuilder implements MyContainerBuilder
{
Double volume = null;
Double density = null;
MyContents contents = null;
public void setVolume()
{
if (contents != null)
{
volume = contents.myDensity() / 3.0;
}
}
public void setContents( MyContents contents )
{
this.contents = contents;
}
public Double myVolume()
{
if (volume == null)
setVolume();
return volume;
}
public Double myDensity()
{
return contents.myDensity();
}
}
class BigContainerBuilder implements MyContainerBuilder
{
Double volume = null;
Double density = null;
MyContents contents = null;
public void setVolume( Double volume )
{
this.volume = volume;
}
public void setContents( MyContents contents )
{
this.contents = contents;
}
public Double myVolume()
{
return volume;
}
public Double myDensity()
{
return contents.myDensity();
}
}
class ContainerDirector
{
Double myResult( MyContainerBuilder container )
{
return container.myVolume() * container.myDensity();
}
}
class MyContents
{
Double density;
MyContents( Double density )
{
this.density = density;
}
public Double myDensity()
{
return density;
}
}
class Test
{
public static void main(String[] args)
{
SmallContainerBuilder smallContainer = new SmallContainerBuilder();
BigContainerBuilder bigContainer = new BigContainerBuilder();
ContainerDirector director = new ContainerDirector();
//
// Assume this comes from the GUI, where an ActionListener knows which Builder
// to use based on the user's action. I'd be having my observable store this.
Double density = 15.0;
MyContents contents = new MyContents( density );
smallContainer.setContents( contents );
//
// Then I would need to tell my observer to do this.
Double results = director.myResult( smallContainer );
System.out.println( "Use this result: " + results );
}
}
容量の計算に異なる方法を使用する 2 種類のコンテナーがあります。コンテナの種類を選択するためのラジオボタンがあり、各ラジオボタンの下に、選択したコンテナに入れることができる項目のコンボボックスがあるとします。コンボボックスの ActionListener は、アイテムを適切なコンテナーに配置し、それをオブザーバブルに保存します (実際に設定されるものは他にもたくさんあります)。オブザーバーにディレクターを使用して適切な値を取得し、オブザーバーが更新するように指示します。 GUI の一部のビュー コンポーネント。