web-dev-qa-db-ja.com

デコレータとファクトリを一緒に使用してオブジェクトを拡張しますか?

OOPとデザインパターンは初めてです。

Tables、Columns(Tableに属する)、Rows(Tableに属し、Columnsを持つ)、Values(Rowsに属する)の生成を処理するシンプルなアプリがあります。これらの各オブジェクトは、列挙型として定義されているプロパティのコレクションを持つことができます。

それらはすべてインターフェースです。状況に応じて、これらの製品の具体的なインスタンスを取得するために工場を使用しました。

現在、これらのクラスを拡張する問題に直面しています。 「SpecialTable」という別の製品が必要だとします。この製品には、特別なプロパティや、「getSomethingSpecial」などの新しいメソッドやプロパティの拡張セットがあります。唯一の方法は、すべての要素を拡張/特殊化することです(つまり、SpecialTableFactory、SpecialTableインターフェイス、およびSpecialTableImplコンクリートを構築します)。たとえば、特殊化する必要のないaddRow(列列、文字列名)などの標準メソッドを使用する予定がある場合はどうすればよいですか?

ファクトリーとインターフェースを継承するという考えは好きではありませんが、SpecialTableにはTableよりも多くのメソッドがあるため、同じファクトリーを共有できないと思います。私が間違っている?

別の質問:実行時に製品のプロパティ(実行時にSpecialTableにアップグレードされるテーブル)を定義する必要がある場合は、デコレータを使用する必要があると思います。工場とデコレータの両方の設計を組み合わせることが可能ですか(そしてどのように)?代わりに、状態または戦略パターンを使用する方が良いですか?

2
Gabriele B

はい、SpecialTableは、Tableを生成するのと同じファクトリ(および同じファクトリmethod)で生成できます。 SpecialTableTableインターフェースによって保証されるメソッドを少なくとも提供する限り、これは問題ではありません(します)。

このような状況は、ファクトリーから返されたオブジェクトがいくつかの動作/機能が保証されている場合(インターフェースTable)、および一部オプションのものがある場合に意味があります(インターフェースSpecialTable)。

したがって、工場から返送されたいくつかの具体的なオブジェクトで利用可能なオプションの追加機能/ものを利用するには、いくつかの選択肢があります。

  • ポリモーフィズムを使用(推奨

  • instanceof(または類似の)を使用します。これを使用して、インターフェースのコンプライアンス/正確なタイピングをチェックできます(可能であればこれを避けてください

ポリモーフィズムを使用

説明のための例:SpecialTableに追加のデータと、特別なテーブルを表すUIに表示される追加のウィジェット 'blarg'があるとします。 UIに「blarg」を追加する必要があることを知るためにSpecialTableを使用するコードが本当に必要ですか?あるいは、必要なUIコンポーネントをいくつかのUIコンテナーに追加するように、外部コードにTableタイプのものを要求させることができますか?次に、呼び出し元のコードは、その正確な型を気にしません-SpecialTableがそれを処理し、コンテナ自体に「blarg」を追加します。このパターンは、delegateパターン(strategyパターンとも呼ばれます)として説明できます。

instanceof(型チェック)を使用

instanceofの使用例:

// Table and SpecialTable are interfaces
Table table = TableFactory.instance().getDefaultTable();

if (table instanceof "SpecialTable") {
  SpecialTable specialTable = (SpecialTable)table;
  specialTable.specialMethod();
}

table.normalMethod();

SpecialTableインターフェースを定義するときは、Tableインターフェースを拡張するものとして宣言し、追加のメソッドのみをリストできることに注意してください。

あなたの工場はどちらのタイプの具体的なオブジェクトも生産します。したがって、BoringTableを実装するTableという具象クラスと、ExcitingTableを実装するSpecialTableという具象クラスがあるかもしれません。

instanceof!に注意してください

一般に、「instanceof」(または一般的に言えば、オブジェクトのタイプに依存するあらゆる種類のif)のようなものは避ける方がよいでしょう。代わりに、ポリモーフィズムを優先する必要があります。これは、共通のタイプの複数の異なるクラスを持ち、それらの実装コードで異なる動作を囲むことを意味します。

これを自問してみてください:Table型(これもSpecialTable型である可能性があります)を使用するクラスは、特別なテーブルであるかどうかに注意する必要がありますか? SpecialTableのある種の実装でその区別を隠すことはできません-単純な古いTableが行う何か別の、何か特別なことをしますか?

0
occulus