みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

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

解決済みの質問

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のオブジェクト指向・デザインパターンについて
理解の乏しいところがあるかと思いますが、ご回答の程よろしくお願いいたします。

投稿日時 - 2010-07-18 21:16:12

QNo.6047572

暇なときに回答ください

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

(1)
ありえないわ。
そもそもinterfaceをprivateな内部interfaceとして定義する必要がないわ。
拡張性を考えたらすべて別クラスとして定義するべきね。
UseStrategyクラスが膨大なコーディング量になってしまうわ。

気持ちは分からなくもないのよ。
・利用者にはUseStrategyのみを意識してもらう
・Strategyの各クラスは公開したくない
っていう考え方でしょう?
だったらprotectedにでもすればいいし
あとのメンテを考えたら分けた方がいいわよ。

(2)
これはStrategyとは関係ない話ね。
答えは、
Strategyとは関係ない別クラスを作成し、その中に処理を記述しそれをコールする
よ。

BetaStrategyとGammaStrategyが持つ意味が一部共通なため
同じ処理になるというのであれば、
この2つの親クラスを作成し、そこに実装するのもありね。
でも、特にそうでないというなら
再利用性も考えて先に書いたやり方をするのがいいわ。

投稿日時 - 2010-07-20 10:17:41

お礼

ご回答いただきありがとうございます。
お礼の方遅くなりまして申し訳ありません。

>気持ちは分からなくもないのよ。
>・利用者にはUseStrategyのみを意識してもらう
>・Strategyの各クラスは公開したくない
>っていう考え方でしょう?

見事に。。上記のように考えて、質問に記載したコードを書きました。
ただ、ご指摘にありますように、今後のメンテ、拡張することを考慮し
別クラスにしようと思います。

>これはStrategyとは関係ない話ね。
>答えは、
>Strategyとは関係ない別クラスを作成し、その中に処理を記述しそれをコールする
>よ。

ご指摘の通りだと思います。#自分の頭が固かったと思います。。。
無理にでもStrategy内に押し込もうしか考えておりませんでした。
再利用性、拡張することを考え、別クラスを作成しようと思います。

再度自分の書いたコードを見直すと、
色々、考慮不足のコードだったと思います。
#書いた当時はこれしかないのではないかと思っていましたが。。。

ご回答頂いた内容から、検討の足りない面がわかりました。
是非今後に活かしていきたいと思います。本当にありがとうございました。

投稿日時 - 2010-07-22 01:26:19

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

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

回答(2)

ANo.2

Java では'_'は、定数を表す識別子を構成する単語の間以外には使わないのが一般的です。
ほかは、#1の方が仰っている通りです。

interface Strategy {
void method1();
void method2();
}

class AlphaStrategy implements Strategy {
public void method1() {
System.out.println("method1 in AlphaStrategy");
}
public void method2() {
System.out.println("method2 in AlphaStrategy");
}
}
class BetaStrategy implements Strategy {
public void method1() {
System.out.println("method1 in BetaStrategy");
}
public void method2() {
System.out.println("method2 in BetaStrategy");
}
}
// Gamma extends Beta
class GammaStrategy extends BetaStrategy {
public void method1() {
System.out.println("method1 in GammaStrategy");
}
}

class SomeThing {
private Strategy strategy;

void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
void doMethod1() {
strategy.method1();
}
void doMethod2() {
strategy.method2();
}
}

public class SomeThingUser {
public static void main(String[] args) {
SomeThing someThing = new SomeThing();

someThing.setStrategy(new AlphaStrategy());
someThing.doMethod1();
someThing.doMethod2();

someThing.setStrategy(new BetaStrategy());
someThing.doMethod1();
someThing.doMethod2();

someThing.setStrategy(new GammaStrategy());
someThing.doMethod1();
someThing.doMethod2();
}
}

投稿日時 - 2010-07-21 22:17:17

お礼

ご回答頂きありがとうございます。
回答が遅くなりまして、申し訳ありません。

>Java では'_'は、定数を表す識別子を構成する単語の間以外には使わないのが一般的です。
つい、C言語の癖で、'_'を付けていました。
今後は、'_'を付けないように気をつけたいと思います。

また、(1)、(2)の疑問・問題を解決したコードを提示頂きありがとうございます。
提示頂きましたコードを参考に、自分のコードを書き直したいと思います。

投稿日時 - 2010-07-26 02:34:05

あなたにオススメの質問