![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
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のオブジェクト指向・デザインパターンについて
理解の乏しいところがあるかと思いますが、ご回答の程よろしくお願いいたします。
No.1ベストアンサー
- 回答日時:
(1)
ありえないわ。
そもそもinterfaceをprivateな内部interfaceとして定義する必要がないわ。
拡張性を考えたらすべて別クラスとして定義するべきね。
UseStrategyクラスが膨大なコーディング量になってしまうわ。
気持ちは分からなくもないのよ。
・利用者にはUseStrategyのみを意識してもらう
・Strategyの各クラスは公開したくない
っていう考え方でしょう?
だったらprotectedにでもすればいいし
あとのメンテを考えたら分けた方がいいわよ。
(2)
これはStrategyとは関係ない話ね。
答えは、
Strategyとは関係ない別クラスを作成し、その中に処理を記述しそれをコールする
よ。
BetaStrategyとGammaStrategyが持つ意味が一部共通なため
同じ処理になるというのであれば、
この2つの親クラスを作成し、そこに実装するのもありね。
でも、特にそうでないというなら
再利用性も考えて先に書いたやり方をするのがいいわ。
ご回答いただきありがとうございます。
お礼の方遅くなりまして申し訳ありません。
>気持ちは分からなくもないのよ。
>・利用者にはUseStrategyのみを意識してもらう
>・Strategyの各クラスは公開したくない
>っていう考え方でしょう?
見事に。。上記のように考えて、質問に記載したコードを書きました。
ただ、ご指摘にありますように、今後のメンテ、拡張することを考慮し
別クラスにしようと思います。
>これはStrategyとは関係ない話ね。
>答えは、
>Strategyとは関係ない別クラスを作成し、その中に処理を記述しそれをコールする
>よ。
ご指摘の通りだと思います。#自分の頭が固かったと思います。。。
無理にでもStrategy内に押し込もうしか考えておりませんでした。
再利用性、拡張することを考え、別クラスを作成しようと思います。
再度自分の書いたコードを見直すと、
色々、考慮不足のコードだったと思います。
#書いた当時はこれしかないのではないかと思っていましたが。。。
ご回答頂いた内容から、検討の足りない面がわかりました。
是非今後に活かしていきたいと思います。本当にありがとうございました。
No.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();
}
}
ご回答頂きありがとうございます。
回答が遅くなりまして、申し訳ありません。
>Java では'_'は、定数を表す識別子を構成する単語の間以外には使わないのが一般的です。
つい、C言語の癖で、'_'を付けていました。
今後は、'_'を付けないように気をつけたいと思います。
また、(1)、(2)の疑問・問題を解決したコードを提示頂きありがとうございます。
提示頂きましたコードを参考に、自分のコードを書き直したいと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Java
-
無名パッケージからのインポート
-
関数内の変数に<summary>コメン...
-
生成されたサーブレットのエラ...
-
キャストについて教えてください
-
C# log4netの使い方
-
C#でほかのファイルにある自作...
-
スーパークラスのインスタンス...
-
親クラスから子クラスへアクセス。
-
Java throwとthrowsの違いについて
-
C# インターフェイスの実装
-
GOF本のデザインパターンのComp...
-
ひとつのファイルにクラスは1つ?
-
Publicとは?
-
指定されたクラスの継承元の確...
-
下記のコードを実行すると、Mai...
-
c++,ある関数のクラスから別の...
-
内部クラスのインスタンスを外...
-
エクセルVBAで、条件に一致する...
-
インスタンス参照でアクセスで...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数内の変数に<summary>コメン...
-
クラス間でのデータ参照
-
C#にて別クラスの関数を使いたい
-
構造 他のクラスの構造体を別...
-
c++,ある関数のクラスから別の...
-
C#のクラスライブラリでメッセ...
-
C++でfriendクラスにしているの...
-
Java リフレクションについて
-
ひとつのファイルにクラスは1つ?
-
C#でほかのファイルにある自作...
-
範囲外の数値を代入したらエラ...
-
無名パッケージからのインポート
-
java-別クラスの変数の使い方を...
-
import と extends について
-
C# インターフェイスの実装
-
親クラスから子クラスへアクセス。
-
a href="..." とServlet
-
継承したクラス側のクラス名の取得
-
Java
-
JSPでbeanプロパティ(配列)を...
おすすめ情報