こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

オブジェクト指向言語で多態性を意識した開発についてご指南お願い致します

多態性を意識した開発を行う場合の良策をご教示ください。
※私の知識が Java に限られるため、内容が Java 寄りになる可能性があります。その場合は申し訳ありません。
ただ、開発時の言語や、規模の大小にかかわらず必要な観点になるかと思い、このカテゴリを選択しました。

(質問)
例えばテキストフィールドを生成する API や、ボタンを生成する API 等を独自で作成(強化)したいと考えています。
その場合、呼び出し元の負担を軽減するために以下のいずれかの実装にしようと考えていますが、いずれの方法が妥当でしょうか?

[1]個別のクラスを用意し、統一した名前のメソッドを用意する
実装例)
class TextFieldFactory ( ) {
 JTextField createItem ( int x ) {
  return //テキストフィールドを返す
 }
 JTextField createItem ( int x, int y ) {
  return //テキストフィールドを返す
 }
}

class ButtonFactory ( ) {
 JButton createItem ( int x ) {
  return //ボタンを返す
 }
 JButton createItem ( int x, int y ) {
  return //ボタンを返す
 }
}

上記の場合、呼び出し元からは『各ファクトリークラス名』と『作成時は createItem メソッドを使用する』事を認識していればよく、多態性は増すと考えています。


[2]特定の一つのクラスを用意し、各種メソッドを用意する
実装例)
class ItemFactory ( ) {
 JTextField createTextField ( int x ) {
  return //テキストフィールドを返す
 }
 JTextField createTextField ( int x, int y ) {
  return //テキストフィールドを返す
 }
 JButton createButton ( int x ) {
  return //ボタンを返す
 }
 JButton createButton ( int x, int y ) {
  return //ボタンを返す
 }
}

上記の場合、呼び出し元は『アイテム生成時は ItemFactory クラスのメソッドを使用する』事を認識していれば良く、多態性が増すと考えます。
反面、1つのソースの実装が膨大になる恐れも(!?)


[3]その他の方法
その他、妙案がありますでしょうか?
※インターフェイス や 抽象クラス も考えましたが、返り値の相違やしグニチャの状況等より、結局[1]と同様、アイテムの種類分必要となるため、今回は検討項目に含めませんでしたが・・・。

経験豊富なプログラマの皆様、ぜひ妙案をご教示ください。

投稿日時 - 2009-01-23 12:35:32

QNo.4653889

困ってます

質問者が選んだベストアンサー

> 今回のアプリにはデザインパターンを取り入れており、
デザインパターンは取り入れようと思って取り入れるものではないので注意してください。
「パターン魔(パターン指向リファクタリング入門からの言葉)」になっている恐れがあります。

> 頂いた内容ですと、Factory としてはインターフェイスのみ用意しておき、実装は必要に応じて、という認識でよろしかったでしょうか。
そうですね。ただ、先ほどの例ではインターフェイスとする利点はほとんどなくて、実装クラスをそのまま記述してしまっても問題ありません。

> ただ、(こちらも説明不足でしたが)使用する各クラスファイルは、パッケージごとに明確に分類しようと考えており・・・、
> (例えば、ファサード役は Director パッケージ、ビルダー役は Builder、ファクトリー役は Factory 等という具合に...)
> Builder 内で Factory パッケージ内のインターフェイスの実装部分を作成する方向では考えておりませんでした。
これはまずい設計です。
パターンによりパッケージを分けるのではなく、依存性によってパッケージは分けるべきです。
詳しくは、「アジャイルソフトウェア開発の奥義」という本で紹介されています。

また、パターンやオブジェクト指向プログラミングに関しては、「デザインパターンとともに学ぶオブジェクト指向のこころ」という本がおすすめですよ。

投稿日時 - 2009-01-23 16:53:00

お礼

ご返答、ありがとうございます。
度々お世話になります。

良書のご紹介をいただきありがとうございました。
ご紹介いただいた書籍については、近日中にも探して目を通してみようと思います。

アプリの構成については、bleis 様のおっしゃる通り、確かにデザインパターンを適用したいという気持ちが働いていたのかもしれません。
そのため、本件の様な内容で悩んでしまったのだと思います。
今回、おふた方にご回答を頂けた事で、今後はもう少しデザインパターンを意識せずに開発に没頭できる気がします。

ただ、現在作成中のアプリでは、私なりに
『 Builder ではコンポーネントの配置(レイアウト)をメインに』、
『 Factory では具体的なコンポーネントの生成の実装をメインに』、
という明確な区別をしており、また、コンポーネント作成はどのアプリでも必須であることから、各 Factory クラスの使いまわしも考慮し、やはり、Factory パッケージは明確に分けるのが良い、と判断していました。
(私の場合、Factory パッケージ内で既に具象クラスを用意しており、bleis 様からご説明のあった、Interface の説明とは若干意識の相違があったかもしれません、パッケージ構造がらみの内容は私も小出しにしてしまったため、ご迷惑をおかけ致しました。)

本件の当初の質問内容についてですが、とりあえず自分の中では方向性が定まりそうです。
ご協力ありがとうございました。

投稿日時 - 2009-01-23 18:43:56

ANo.3

このQ&Aは役に立ちましたか?

28人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.2

Javaのコードも間違ってますね・・・
以下ワルノリしたコード(コンパイルすらしてません)。
IDEの補完機能が使えれば、さくさくコーディングできますよ(論点が違う?)。
対応しなければならないコンポーネントが追加になったら、そのコンポーネント用のビルダインターフェイスと実装クラスを作成し、GuiComponentのフィールドを追加します。もちろん、GuiComponentに追加せず、実装クラスをそのまま生成して使ってもOKです。

public final class GuiComponent {
 private GuiComponent() {}
 public static final TextFieldBuilder TEXT_FIELD = new TextFieldBuilderの実装クラス();
 public static final ButtonBuilder BUTTON = new ButtonBuilderの実装クラス();
}

public interface GuiComponentBuilder<Self extends GuiComponent<Self, Component>, Component extends JComponent> {
 Self location(int x, int y);
 Component create();
}

public interface TextFieldBuilder extends GuiComponentBuilder<TextFieldBuilder, JTextField> {
 TextFieldBuilder text(String text);
}

public interface ButtonBuilder extends GuiComponentBuilder<ButtonBuilder, JButton> {
 ButtonBuilder label(String label);
}

// usage
JTextField textField =
 GuiComponent.TEXT_FIELD
       .location(x, y)
       .create();
JButton button =
 GuiComponent.BUTTON
       .location(x, y)
       .label("ボタン")
       .create();

ちなみに、この例だとGuiComponentの中に実装クラスをハードコーディングすることになるため、インターフェイスを用意する意味はないです。

投稿日時 - 2009-01-23 14:52:44

お礼

ご返答、ありがとうございます。
説明不足ですみません。
(IDE としては Eclipse を使用しています。)
今回は『どういう事を意図したいか』をご認識頂ける事を優先し、抜粋したため、必要な部分まで削りすぎた結果です orz (スミマセン)

ちなみに、実動作環境では以下の様な感じ。。。
---------------------------
private JButton btn = null ;

public JButton createItem ( String value, int x, int y ) {
 btn = new JButton ( value ) ;
 btn.setPreferredSize ( new Dimension ( x, y ) ) ;
 return btn ;
}

public JButton createItem ( String value, int x, int y, int width, int height ) {

 btn = new JButton ( value ) ;
 btn.setBounds ( x, y, width, height ) ;
 return btn ;
}
//さらに続く・・・
---------------------------

今回のアプリにはデザインパターンを取り入れており、入り口となるクラスを絞り、その中でアプリの各部分を整形する各 Builder クラスを呼び出し、更にその Builder クラス内で、ボタンやラベルが必要な時に Factory クラスを呼び出し各コンポーネントを生成する・・・
という構成で開発を進めております。

頂いた内容ですと、Factory としてはインターフェイスのみ用意しておき、実装は必要に応じて、という認識でよろしかったでしょうか。
ただ、(こちらも説明不足でしたが)使用する各クラスファイルは、パッケージごとに明確に分類しようと考えており・・・、
(例えば、ファサード役は Director パッケージ、ビルダー役は Builder、ファクトリー役は Factory 等という具合に...)
Builder 内で Factory パッケージ内のインターフェイスの実装部分を作成する方向では考えておりませんでした。

貴重なご意見を頂き、誠にありがとうございました。
今後の開発にも参考にさせて頂きたいと思います。

投稿日時 - 2009-01-23 16:23:37

ANo.1

1も2も、全くポリモーフィズムになってない気がしますが。
これは、ただ名前を統一するだけでポリモーフィズムには関係ないです。
どちらかというと、命名規則に近いんじゃないでしょうか。

1か2のどっちがいいかと問われると、TextとButtonの関係性がはっきりしませんが、相互関係がないとしたら1のほうがいいと思います。

クラス分けを考える際は、責務について考えると分かりやすいと思います。

投稿日時 - 2009-01-23 14:31:25

お礼

ご返答いただきありがとうございます。
※テキストフィールドとボタンはただ単に例としてあげるのに都合が良かったのみで、特別な意図はありません。

確かに、命名規則と言われればそれだけですね...(反省)
私の思う”多態性”の認識にズレがあるのかな・・・

ただ、Interface や 抽象クラスを用意する意図としては、命名規則の統一も必要な機能ですよね。。。
※今回は独りで趣味開発ですので、モックオブジェクトとしては Interface 等を用意する必要は今のところありませんが。。。
※また、質問内容[3]に記載しましたとおり、各 Factory とも返り値が違うため作るのにも苦労しそうですし・・・。

私の意図としては、例えば[1]の場合ならばテキストフィールドとボタンの生成がそれぞれ以下の様な記述で行える認識で、

new TextFieldFactory().createItem( "テスト テキスト" );
new ButtonFactory().createItem( "テスト ボタン" );
※ごめんなさい、サンプルでは引数 int 型にしていましたね、String 型に読み替えてください(誤記でした)。

つまり、クラス名を変えだけで生成するアイテムを変更できる。
= > 多態性がますのではないかと。。。

或いは [2] の場合ならメソッド名を変えるだけで...(同上)


ただやはり、おっしゃるとおり命名規則にしかなっておらず、オブジェクト指向で説明される多態性と、私の意図とにそもそも差異があったかもしれません。。。
それに本当の意味で命名規則を設けるならば、それこそ面倒がらずに Interface を作るべきですよね。(再度反省)

貴重なご意見ありがとうございました。
再度検討してみたいと思います。

投稿日時 - 2009-01-23 17:00:24

あなたにオススメの質問