- PR -

EJBHomeFactory(Service Locator)パターンはなぜわざわざFactoryをインスタンス化?

1
投稿者投稿内容
やまろう
常連さん
会議室デビュー日: 2003/10/13
投稿数: 35
お住まい・勤務地: 埼玉・東京
投稿日時: 2004-01-21 17:08
EJBHomeFactory(Service Locator)パターンはなぜFactoryをインスタンス化するのでしょうか?

一般的なEJBHomeFactory(Service Locator)は以下のように
FactoryをSingleton化しています。

public class EJBHomeFactory {
 private static EJBHomeFactory singleton = new EJBHomeFactory();

 private Context context;

 private HashMap homes = new HashMap();
 
 private EJBHomeFactory() {
  try {
   context = new InitialContext();
  } catch (Exception ex) {
   throw new SystemException(ex); //RuntimeExceptionにラップ
  }
 }

 public static EJBHomeFactory getInstance() {
  return singleton;
 }
 public EJBHome getEJBHome(String ejbName, Class homeClass) {
  //HashMapにあるhomeかContextを使ってhomeを取得してreturn
 }
}

使う側は、

EJBHomeFactory factory = EJBHomeFactory.getInstance();
HogeHome home = (HogeHome)factory.getEJBHome("Hoge", HogeHome.class);

っていうふうにFactoryをインスタンス化してHomeを取得という
2ステップの呼び出しが必要です。

もし、以下のようにContextとHomeのMapをSingleton化したら?

public class EJBHomeFactory {
 private static Context context = createContext();
 private static HashMap homes = new HashMap();

 private static Context createContext() {
  try {
   return new InitialContext();
  } catch (Exception ex) {
   throw new SystemException(ex); //RuntimeExceptionにラップ
  }
 }

 public EJBHome getEJBHome(String ejbName, Class homeClass) {
  //HashMapにあるhomeかContextを使ってhomeを取得してreturn
 }
}

使う側は、

HogeHome home = (HogeHome)EJBHomeFactory.getEJBHome("Hoge", HogeHome.class);

と1ステップでHomeを取得出来ます。この方が使う側からすると楽だと思うのですが、
なぜ、わざわざFactoryをインスタンス化してからHomeを取得する設計になっている
のでしょうか?キャッシュしたいのはContextとHomeオブジェクトであり、
どちらの実装でもそれが可能であり、どちらも処理の詳細を隠蔽しています。
わざわざFactoryをインスタンス化するとメリットがあるのでしょうか?

単に一般的なSingltonパターンを適用したからとしか思えず、

「インスタンス化した方がオブジェクト指向っぽいしぃー」

っみたいな・・・、んなこたぁないよね(タモリ)。



[ メッセージ編集済み 編集者: やまろう 編集日時 2004-01-22 09:44 ]
ぽん
大ベテラン
会議室デビュー日: 2003/05/13
投稿数: 157
投稿日時: 2004-01-21 17:56
引用:

やまろうさんの書き込み (2004-01-21 17:08) より:

(Service Locator)パターンはなぜFactoryをインスタンス化するのでしょうか?


EJBHomeFactoryの事は全く知らないのですが。

インスタンス化を行うのは、多態性の事を念頭に置いているのからでは無いでしょうか?
例えば、下記の様な関数があった場合、static関数では対応出来ません。
コード:

public void func(EJBHomeFactory factory) {
factory.getEJBHome("Hoge", HogeHome.class);
}



多態性を使用するかもしれない関数はstaticにするべきでは無いと思っています。
(絶対に多態性を使用しない関数はstaticにしてます)

「多態性が利用出来る」というのもSingletonパターンの利点のひとつです

[追記]
EJBHomeFactoryのインスタンスが複数になった場合も、static関数だと対応出来ませんね。

[ メッセージ編集済み 編集者: ぽん 編集日時 2004-01-21 18:06 ]
YOU@IT
ぬし
会議室デビュー日: 2002/03/29
投稿数: 284
お住まい・勤務地: 大阪
投稿日時: 2004-01-21 18:03
Service Locatorパターンに関する話題と言うよりは、Singletonパターン
に関する問題のように思います。

Singletonとstaticメンバで構成されたクラス(以下ユーティリティクラス)との
違いやどちらを選択すべきかについては、結構あちこちで議論になってますよね。
# 結論としてはケースバーケース...になってしまうんでしょうけど

私の場合、Singleton or ユーティリティクラスの判断基準は拡張性を持たせるか否かです。
ユーティリティクラスのstaticメンバは拡張しにくい(ポリモルフィズムも働かないし)ので、
拡張性を持たせたい場合はSingletonを選択します。
# SingletonパターンとAbstractFactoryパターンの組み合わせとかが考えられるかと。

でもたいていはSingletonを選択してます。
Singleton#getInstance()とかするのも大して負担にはなりませんし。

やまろう
常連さん
会議室デビュー日: 2003/10/13
投稿数: 35
お住まい・勤務地: 埼玉・東京
投稿日時: 2004-01-23 10:28
ご意見ありがとうございます。

ちょっと屁理屈なんですが、
ぽんさんのおっしゃる、「多態性を利用するためにインスタンス化する」
というご意見はこのEJBHomeFactoryには当てはまらないと思います。

多態性を利用するのなら、

public class EJBHomeFactory {

ではなく

public class EJBHomeFactory implements IEJBHomeFactory {

public interface IEJBHomeFactory {
 public EJBHome getEJBHome(String ejbName, Class homeClass);
}

で、

public void func(IEJBHomeFactory factory) {
 factory.getEJBHome("Hoge", HogeHome.class);
}

としないと、多態性にならないと思います。
とはいえほんと屁理屈ですね。ぽんさんはおそらく
クラスの実装を変えてimplements 〜 にした時に、呼び出し側のコードを変えずに
済むという意味でおっしゃったのでしょうから。

結局、将来的な拡張性のためってことなんですね!
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2004-01-23 11:50
実際に実装したことのあるServiceLocatorですが、異なるコンテキストごとにインスタンスが
必要なので、getInstanceに引数を持たせてその引数によってコンテキストごとのインスタンス
を返すようにしたことがあります。

Singleton一般の話はともかく、ServiceLocatorに関していえばこのような要求はよくある
ことだと思います。
1

スキルアップ/キャリアアップ(JOB@IT)