• ベストアンサー

Factory Method パターンの利点

いつも参考にさせて頂いてます。java で良い設計ができないか試行錯誤している時に、デザインパターンなる定石パターンがあることを知りました。そこで、Factory Method パターンについて、 ・どのようなケースで利用するのか? ・利点は何か? を簡単に説明して頂けたらと思います。お願いします。

  • Java
  • 回答数9
  • ありがとう数10

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

  • ベストアンサー
  • kacchann
  • ベストアンサー率58% (347/594)
回答No.8

#3です。 自信なし。 --- (たぶん)最重要な側面(のうちの1つ)を書き忘れてました。 前述の「CollectionとIterator」の例で言うと、 sunのJDKについてくる「標準クラスライブラリとしてのCollection」は、 Vectorだったり、LinkedListだったり、 その他いろいろ、 いくつか「すでに存在」していると思うのですが、 ここで、「sunの標準ライブラリに存在しない、 自分オリジナルのCollection、MySupecialListというのを作りたい!」 と思ったとします。さらに 「このMySupecialListに合うIteratorは、 既存のsun標準ライブラリのIteratorの中には見当たらず、 これも自作するほかないんだよな~」 というケース。 いわば、 『"プラグインな"Collectionを使う時』 です。 このケースでは、 自作者は単に class MySpecialList implements Collection{  …  (中略)  …  public Iterator iterator(){   return new MyIterator();  } } というクラスを作成するだけで、 利用者はこの自作Collectionを、 他のCollectionを使う時と"全く同じやり方で"使えるようになります。 (そうであるべき。) 仮に「Factory Methodパターン」が使われていなかった場合、 利用者が自作Collectionを使う際には 他の標準Collectionを使う時と"全く同じやり方で"使う手立ては ないと思います。 『Collectionプラグイン』開発者としては、 利用者に"特別な使用法"を強いるわけにはいきませんし…。 --- 言い換えれば 「追加しても」利用者にばれない というカンジでしょうか…。 --- おそらく同様のケースは、 「フレームワーク(※Eclipseとか、いろいろ)の、 プラグイン部」(プラグイン開発) で「必須な」ような気がします。

その他の回答 (8)

回答No.9

FactoryMethodパターンについてお答えします。 FactoryMethodは、サブクラスとサブクラスを必ずペアで利用する場合に利用するパターンです。 例えば、人と携帯電話の関係を表す場合に利用します。 人は「田中さん」「鈴木さん」、携帯電話は「X999」「Y111」があるとし 「田中さん」が「X999」、「鈴木さん」が「Y111」という携帯電話を持っていたとします。 classは以下とします。 abstract class 人間(){ abstract public String get名前(); } class manA extends 人間{ public String get名前(){return "田中"} } class manB extends 人間{ public String get名前(){return "鈴木"} } abstract class 携帯電話(){ abstract public String get機種(); } class telephoneA extends 携帯電話{ public String get機種(){return "X999"} } class telephoneB extends 携帯電話{ public String get機種(){return "Y111"} } 「田中さん」と持っている「携帯電話」の情報を知りたい場合、 人間 man = new manA(); 携帯電話 telephone = new telephoneA(); System.out.println(man.get名前()); System.out.println(telephone.get機種()); とすれば、表示出来ますが、 情報を探す際に、「田中さん」が「X999」を持っている(組合せを知っている)必要があります。 「田中さん」「鈴木さん」だけなら良いのですが、これが100人、1000人となった場合、全部の組合せを覚えておくのは大変です。 そこで、プログラムの中に記述してしまいます。 abstract class 人間(){ abstract public String get名前(); abstract public 携帯電話 create携帯電話(); } class manA extends 人間{ public String get名前(){return "田中"} public 携帯電話 create携帯電話(){return new telephoneA()} } class manB extends 人間{ public String get名前(){return "鈴木"} public 携帯電話 create携帯電話(){return new telephoneB()} } こうすれば 人間 man = new manA(); 携帯電話 telephone = man.create携帯電話(); System.out.println(man.get名前()); System.out.println(telephone.get機種()); の形式で、 人と携帯電話の組合せが分からなくても、自動的に携帯電話情報を取得できます。 一人でプログラムを作っている場合は、価値があるかどうか微妙ですが、 実際の業務では、第三者が情報を探す際に、 人classだけで、携帯電話の情報を知ることが出来れば、大変便利です。 (第三者は、組合せを知らなくても良い) これがFactoryMethodの利点です。 FactoryMethodを利用する際に、抽象化(ポリモーフィズム)を利用しますが、それ自体が本質ではありません。

aerosmith777
質問者

お礼

ご回答ありがとうございます。 教えてもらった設計をすることで、利用者には誰がどの携帯電話を使ってるかまで意識する必要がなくなりますね。 質問してわかったのですが「java の抽象化の利点=Factory Method の利点」と勘違いしていたケースが多々あります。ご迷惑かけました ^^ 自分も紹介された本を含め、2冊ほどデザインパターン関連の本を購読しています。解説された利点も紹介されていて、確かに使えるパターンですね。 パターンをより効率よく利用してよい設計を心がけたいものです。

  • dekopa-
  • ベストアンサー率42% (161/378)
回答No.7

私の書き方も悪かったんでしょうけど…… >「継承はそのツリー構造内でカプセル化が破られる」 >これがFactory Method パータンにそぐわない理由は 両者は関係ありません。「Javaで実装する一般的スタイルがinterfaceな理由」を補足説明しただけで、どちらもFactoryMethodで用いて良いのです。 インターフェースの実装か継承か、という問題は既に本件から離れています。それをまずご理解ください。 >「継承はそのツリー構造内でカプセル化が破られる」とは、継承クラスで新たにメソッドやプロパティーを定義することができることをおっしゃっていますか? いいえ、違います。機能の「追加」はカプセル化とは別です。むしろあって当然です。 1.protected宣言があるため、継承したクラスに一部のインターフェースが流出する 2.継承の機構上、親クラスの変更はどうしても全ての子クラスに波及する が、近年継承を避けるようになった主な理由です。 しかし、goto文が「使うべきときに使えば有効」であるように、継承も「使ってはいけない」とみなされているわけではありません。 単に、「何が何でも継承」という一時の風潮を戒めただけです。 >※ 参考書は本屋で見てこようと思います。 著者じゃありませんが、買ってください。良書は身銭を切り、大事な部分に積極的に線を引いて「自分のもの」にすべきです。

aerosmith777
質問者

お礼

どうも、インターフェイスについての理解が足りなかったようです。しかし、いずれのパターンも多様性を意識して作られているので、上記説明は大変参考になりました。 また、勉強していくうちに、私の返答がFactory Method に関して言及している訳ではないことも理解できました。 以降はjava の経験を積むとともに、教えて頂いた書籍で勉強しようと思います。 今回はいろいろと教えていてだき、ありがとうございました。

  • kacchann
  • ベストアンサー率58% (347/594)
回答No.6

#5です。 >Factory Method の利点とは >「利用クラスがインターフェイスの実装を知る必要がないため、 >実装クラスの変更がしやすくなる、 >つまり再利用しやすいこと」 >でしょうか? そういう一面もあります。

aerosmith777
質問者

お礼

自分の理解の再確認ができ、大変参考になりました。ありがとうございます。

  • kacchann
  • ベストアンサー率58% (347/594)
回答No.5

#4です。#4に捕捉。 自信なし。 --- #4で 「享受者の利点」 を書きましたが、 これは主に、 「抽象(基本)型と抽象的な操作インターフェースで コードを記述する利点」 であって、 「Factory Methodを使う利点」 がはっきりしませんね…。 --- あるCollectionを使っている最中、 その「操作ごとに」、操作子たるIteratorを使いたい(生成したい)となれば、 普通に考えれば、 ^^^^^^^^^^^^^^ "Iteratorのコンストラクタを呼んでインスタンスを得る" しかありませんが、 コンストラクタ呼び出しをしてしまえば、 ・「コンストラクタ呼び出し」は 「抽象的な操作インターフェース」ではないので、 「抽象的な操作インターフェース」を使うことによる利点が享受できない。 ・「コンストラクタ呼び出し」するということは、 「生成すべきIteratorクラスの具体名をいちいち知っていなきゃならない」 ということでもあります。 これらの不都合を解消するのが、 「コンストラクタをメソッドにくるんで (本来コンストラクタが持つ)インスタンス生成機能自体を 抽象操作インターフェスにする」 という方法です。(このメソッドのことをFactory Methodと言う)

  • kacchann
  • ベストアンサー率58% (347/594)
回答No.4

#3です。#3の捕捉。 自信なし。 --- #3で、 >意味付けすれば、 >「ある型(Person)があり、 …中略… >そのような機能を提供するしくみ」 と書きましたが、 これは「仕組みを構築する側の視点」であって、 「享受する側の視点」で言えば、 「(ある状況に)もっともふさわしいインスタンスが、 「一つの決まったいんた~ふぇ~す(命令)」で生成できて、 しかもそれは基本型で受け取れちゃうんだよね。 理由はよくわからないけど」 ということになると思います。 「享受者」があるCollectionオブジェクトを使っている最中に、 そのCollectionオブジェクトにふさわしいIteretorが欲しくなった時、 その「ふさわしいIteratorの具体名」を知らずとも(※というか たいてい「知るわけない」)、 Iterator ite=coll.iterator(); という「一定の決まった記述」で、適切な(collに応じた)Iteratorが受け取れているという。 (というか享受者にとってIteratorはあくまで「単なるIterator」でしかなく、 具体的にそれが「ultraHogeHogeIterator」かどうかは関知しないし 関知するべきでない) また、これによって、 「(collオブジェクトの種類に変更があっても)「Iterator取得部分の」 コード及びその後の「取得Iterator」に対する操作部分 には変更が生じない。 (言い換えれば、collの種類が何であろうと、 まったく一定のコードでIterator操作できる)」 ということをも意味します。つまりまるっきり「Iteratorの具体名を隠し続けて」 操作できるわけです。

aerosmith777
質問者

お礼

こちらは、オブジェクトを利用する(クラス) 立場からの利点を書かれているのですね。 オブジェクトの実装クラスと利用クラスが分別できている場合、利用クラスでは Iterator ite=coll.iterator(); のように利用してもIterator の実装クラスを知る方法はなく、また知る必要もないですね。 つまり、この例でいえる事=Factory Method の利点とは、 「利用クラスがインターフェイスの実装を知る必要がないため、実装クラスの変更がしやすくなる、つまり再利用しやすいこと」 でしょうか?

  • kacchann
  • ベストアンサー率58% (347/594)
回答No.3

素人です。自信ありませんが…。 --- 理屈ぬきで、実例を見たほうが理解が早いかも。 Collection#iterator() List#toArray() などは Factory Methodパターンだと思います。 他にも、sunのコレクションフレームワークや、 他のクラスライブラリのソースコード見ていると、 いたるところで"普通に"ちょこちょこ出てくるみたいです。 --- あと、テンプレート的・内部的な、こういうのも。 abstract class Nation{//国  public void seizi(){//政治   Person person =boss();//一番えらい人   person.enzetu();//演説   person.kaiken();//会見   person.ohiru();//昼食   person.Jim();//事務  }  abstract protected Person boss(); } 「seizi()を見るには各国、boss()を実装してください」 みたいな。 --- Factory Methodパターンとは、 個人的には、とりあえず意味付けせずに、単純に ^^^^^^^^^^ 「コンストラクタ呼び出し」をメソッドでくるむことによって そこに「いんた~ふぇ~す性」を帯びさせただけ。 という「事実だけ」を捉えるようにしてるかも。 意味付けすれば、 「ある型(Person)があり、 この型を"基本型にもつ"インスタンスを生成したいのだが、 『状況・背景(Nation)に応じて、(基本型の)継承先の型を決定』 してその継承型インスタンスを、(一環した"いんた~ふぇ~す"(命令)を通して)生成したい。 そのような機能を提供するしくみ」 てなところだと思うんですが…。 日本なら小泉、 ロシアならプーチン、 アメリカならブッシュ、 みたいな。

aerosmith777
質問者

お礼

テンプレートパターンと併用するケースは分かりやすく、理解できました。ありがとうございます。 この例を見ても、boss() のように国によって異なる実装がある場合に戻り値としてインターフェイスを使うようですね。そして、親クラスでアルゴリズムを決めておいて、サブクラスでインターフェイスの実装を行う。だから自然と戻り値もインターフェイスとなるのですね。 テンプレートパターン、Factory Method パターンの実例があると分かりやすいです。

  • dekopa-
  • ベストアンサー率42% (161/378)
回答No.2

>戻り値をインターフェイスにする理由はオブジェクト利用者にFactory Method が返すオブジェクトを意識させないためですよね? 違います。 書いてみると分かりますが、複数の実装をもつ場合、「クラスLoggerを継承する」か「インターフェースILoggerを実装する」しかありません。 どちらも、多態性の機能を利用して上位(クラス/インターフェース)に下位の実装クラスのインスタンスを代入して返します。 となると戻り値の型は「継承もとのクラスか」「実装元のインターフェースか」、別の意味では「各Loggerはクラスから派生するかインターフェースを実装するか?」を検討することになります。 Javaは多重継承をサポートしていません。また継承はそのツリー構造内でカプセル化が破られるという弱点があるため、現在は継承は極力使わず、インターフェースを実装するのが主流となります。 なので「戻り値の型はインターフェースが一般的」と書いたのです。

aerosmith777
質問者

お礼

何度もお手数掛けますが、「継承はそのツリー構造内でカプセル化が破られる」とは、継承クラスで新たにメソッドやプロパティーを定義することができることをおっしゃっていますか? これがFactory Method パータンにそぐわない理由は、 通常、オブジェクト利用者はメソッドを利用する場合、インターフェイスの仕様にあるメソッドを使う。が、継承クラスの場合は継承クラス独自のメソッドを実装できるため、オブジェクト利用者が知らない実装ができてしまう。つまり、継承したクラス独自のメソッドが作れてしまうことが問題。 という理解でよいのでしょうか?

  • dekopa-
  • ベストアンサー率42% (161/378)
回答No.1

・どのようなケースで利用するのか? 主に、インタフェースに対して実装クラスが複数ある場合ですね。 FactoryMethodの場合、Javaでは戻り値の型をインタフェースにするのが一般的です。 たとえばログ出力するLoggerを生成するLogger.getLogger()の場合、 出力先は「ファイル」「コンソール」「syslog(Unix)」「イベント(Win)」「ネットワーク」「パイプ」等が考えられます。 出力先に応じた実装クラスを生成して返してくれるのが、FactoryMethdです。 ・利点は何か? 関連を少なくします。 インターフェースとファクトリ以外に、クライアントは知る必要がありません。実装クラスをimportしたりする必要もないし、実装クラスが増えても関係ありません。 とりあえず、参考書籍を挙げておきます。分かりやすいですよ。

参考URL:
http://www.hyuki.com/dp/
aerosmith777
質問者

お礼

お返事ありがとうございます。 質問してから私もWEB+DB の特集などを参考にFactory Method パターンの利用価値について勉強してますが、なにせ初心者なのでなかなか理解できません。追加で質問させてください。 「Javaでは戻り値の型をインタフェースにする」とありますが、戻り値をインターフェイスにする理由はオブジェクト利用者にFactory Method が返すオブジェクトを意識させないためですよね?例えば、ログ出力をsyslog にする場合、getLogger( "syslog" ) のように、利用者が欲しいオブジェクトをFactory Method に教えている意味では、意識していると思うのですが。戻りをインターフェイスにする価値がいまいち分かってないと思います。 お手数ですが、よろしければ教えてください。 ※ 参考書は本屋で見てこようと思います。ありがとうございます。

関連するQ&A

  • Abstract Factoryパターンについて

    JAVAの勉強をしはじめたのはいいのですが、 Abstract Factoryパターンについて 「これを使うことによってどのようなメリットやデメリットがあるか。」 「また、どのような状況において適用されるのか。」 という点が分かりません。 関連するパターンが多いようなのでなるべくしっかりと理解しておきたいのです。 コレについて詳しい説明をお願いします。

  • Strategyパターンを用いた実装について

    Strategyパターンを用いた実装について 現在Javaを勉強しており、 Strategyパターンを用いた以下の実装を考えています。 public class UseStrategy { private Strategy strategy; public void doSomthing(int num) { switch (num) { case 0: strategy = new AlphaStrategy(); break; case 1: strategy = new BetaStrategy(); break; case 2: strategy = new GammaStrategy(); break; } // 変数strategyを用いて処理を続行していく // ... } private interface Strategy { public abstract void method_1(); public abstract void method_2(); } private class AlphaStrategy implements Strategy { @Override public void method_1() { //do something } @Override public void method_2() { //do something } } private class BetaStrategy implements Strategy { @Override public void method_1() { //do something } @Override public void method_2() { //do something } } private class GammaStrategy implements Strategy { @Override public void method_1() { //do something } @Override public void method_2() { //do something } } } つきましては、以下ご質問させてください。 (1)Strategyパターンの実装において、  上記UseStrayegyクラスのように、あるクラスの入れ子クラスとして  Strategyインターフェース及び、その実装クラスを実装する方法は  普通でしょうか?    それとも、入れ子クラスとしてではなく、Strategyインターフェース、  その実装クラスを全て 別クラスファイルに分けた方が良いのでしょうか? (2)例として、  BetaStrategy.method_2()とGammaStrategy.method_2()の処理が全く  同じだったとします。その場合、共通となる処理を一つのメソッド化し、  そのメソッドをBetaStrategy.method_2()とGammaStrategy.method_2()から  コールしたいと考えております。  その際、共通となる処理メソッドの実装箇所としては、以下のいずれが良いのでしょうか。   (A)Strategyインターフェースを抽象クラス化し、二つの共通処理メソッドを実装する。  (B)UseStrategyクラスに、共通処理を実装する。    それとも、上記の様なケースがある場合Strategyパターンは不適切でしょうか。 文面に分かりづらい面や、Javaのオブジェクト指向・デザインパターンについて 理解の乏しいところがあるかと思いますが、ご回答の程よろしくお願いいたします。

    • ベストアンサー
    • Java
  • 無線のパターンアンテナについて

    無線に関して全くの無知です。 送受信を行える微弱タイプの無線リモコン(スマートキーの様なモノで通信距離は5m程度)の作製を考えています。 使用する無線ICはTI社のCC1101(315MHz)になります。 無線IC以下の回路設計を行う上で、データシートの推奨回路(データシート25ページ目)を参考して設計を進めているのですが、アンテナの部分をどの様にしたら良いか全くわかりません。 推奨回路のアンテナ部には『アンテナ 50Ω』との表記がありますが、PCBパターンを使用したアンテナでの設計を行いたい(コスト、ケース仕様から)と考えています。 パターンアンテナの設計に関する参考サイトを探したのですが、自分のレベルにあったサイトがありませんでした。 ご指導頂けますでしょうか? よろしくお願い致します。 http://www.tij.co.jp/jp/lit/ds/symlink/cc1101.pdf

  • C++で他からの削除を禁止させたい

    C++で、Factoryパターンで利用者にオブジェクトを、基本クラスの型で提供して使わせる部分を設計&実装しようとしているところです。 利用者に、提供したオブジェクトをdeleteで削除されると、管理しているFactoryがCoreを吐いて落ちてしまうと思いました。 利用者にはオブジェクトの寿命を気にせずに使ってもらいたいのです(そのための管理のしくみなので)。でも、設計書にどんなに謳っても、やっちゃう人はやっちゃいます。 deleteをさせないようにするにはどうすればよいでしょうか?friend以外で解決策はないでしょうか?

  • ホームページのリンクメニュー

    HPのリンクメニューにナビゲーションを利用している例をよく見かけますが、みなさんはどのように作ってるのでしょうか。 具体的な例としては下記URLのようなものですが、JAVAを使用せずにCSSだけでデザインできる利点もあるようです。 使用例「グローバルナビゲーションのロールオーバーをJavaScriptを使わず、CSSのみで実現する」 ​http://css-happylife.com/template/07/​ ​http://blogimg.goo.ne.jp/user_image/5e/43/9620a56f8595f82e251d8c79b...​ 現在までは各リンクボタンを一枚一枚作成して、それをマウスを当てたときに色違いになるようにJAVAを利用しておりました。 それが一枚で済む利点は興味深いものがあったので自分で作ろうと思ったんですが、これだけ升目があると縦横の仕切り線や文字の位置にばらつきができてしまいましてうまく作れません。 しかも格段が色違いになっており、どうやってアレンジしていいのかさっぱりわかりません・・・ 一応父親のPCにAdobe Photoshop CS3が入ってるので、これを借りて試行錯誤しながら作ってみましたが、一週間考えてもダメでした。 何かいいアドバイスお願いします!

  • javaでswfファイル生成

    javaでswfファイル生成 題名の通りjavaでswfファイルを出力、といったことをやりたいと思っています。 そこで、javaにはそういったライブラリとかはあるのでしょうか? 自分が調べた中ではjavaswfというものがあったのですが、試行錯誤してみてもエラー(importが一部だけできない)が消えなかったので、違うアプローチを考えています。 参考になるサイトなど教えて頂けたらありがたいです。

    • ベストアンサー
    • Java
  • クラス設計の良い参考書を教えてください

    このたび、仕事で初めてC++を前提にした設計をすることになったのですが、プログラミングも含め、C++自体が全く初めてです(オブジェクト指向自体も初めてです)。あまり時間もないので、良い参考書を探しております。特に、良いクラス設計の思想、設計例などが解説されている参考書などありませんでしょうか。時間が無いので極力邦書を希望します。GoFの再利用のためのデザインパターンの本(業務命令により購入済み)と、平行して進めるつもりですので、これと思想が違わないものが希望です。

  • オブジェクト指向で設計・プログラミングできるようになるために…

    どう勉強すればいいのでしょうか? 一応javaを少しずつ勉強していて、簡単なアプレットやウィンドウアプリケーションは作れるようになったと思うのですが、オブジェクト指向で設計?モデリング?となると、手が出ません…。 また、デザインパターンというもの(よくは知りません)を勉強するのとオブジェクト指向を勉強するのとは関係がありますか? よろしくお願いします。

  • PCからDVD-R RWへ 

    Vaio PCV-JX11を使っていて、MediaPlayer10、GigaPocket リアルプレーヤーがあります。 GigaPocket で録画はできるようになったのですが、これを DVD-RやRWに 書き込む込むことはできないのでしょうか?? できるのであれば やり方を教えてください。 他の方法があれば(上記のものを使わなくても)知りたいです。 又 MediaPlayer10というのはDVDが見れるというほかは、何が利点なのでしょうか? 初歩的な質問ばかりで すみません。 説明書やHPで 試行錯誤しているのですが 全くわかりません。  よろしくお願いします。

  • HTML ドロップダウンメニュー 教えてください!

    ナビゲーションのドロップダウンメニューを作りたく、 ↓↓このサイトを流用し、こんな感じで、↓↓ http://ezorisu-web.com/web-design/archives/356 試行錯誤しています。 現在作っているサイトが、flashに重なって半透明の透過PNGのナビゲーションがあり、IE6でも半透明に見えるよう、ジャバスクリプトを使用しています。 ここで、ジャバスクリプトを使用しているのが原因かわかりませんが、ジャバスクリプトを使用したドロップダウンメニューをつくろうとするとPNGが半透明じゃなくなってしまいます。 そのため、現在、上のサイトを参考にCSSだけでのドロップダウンメニューを作っているのですが、上のサイトどおり作ると、IE6が、ドロップだうんしません。 何かいい方法はないでしょうか?? ※↓ジャバスクリプトは↓ここからダウンロードしました。 http://monodez.com/create/pngfix.html

専門家に質問してみよう