📢 この記事は gemini-2.5-flash によって翻訳されました
Strategy Pattern オブジェクトの振る舞いパターン
目的
一連のアルゴリズムを定義して、それぞれをカプセル化し、互いに置き換え可能にするよ。このパターンを使うと、アルゴリズムをそれを使うクライアントとは独立して変更できるようになるんだ。
構造

ポイントはね:
Strategy(戦略)は、サポートするすべてのアルゴリズムの共通インターフェースを定義するよ。Contextはこのインターフェースを使って、特定のConcreteStrategyが定義するアルゴリズムを呼び出すんだ。
ConcreteStrategy(具体的な戦略)は、Strategyインターフェースを実装して具体的なアルゴリズムを実現するんだ。
Context(コンテキスト)は、ConcreteStrategyオブジェクトで設定されるよ。Strategyオブジェクトへの参照を保持していて、Strategyがそのデータにアクセスするためのインターフェースを定義することもできるんだ。
適用できる場面
Strategyパターンは、こんなときに役立つよ:
多くの関連するクラスが、振る舞いだけが違う場合。「戦略」は、複数の振る舞いの中から1つを使ってクラスを設定する方法を提供してくれるんだ。
あるアルゴリズムの異なるバリアントを使う必要がある場合。例えば、異なる空間/時間トレードオフを反映するアルゴリズムをいくつか定義するとか。これらのバリアントがアルゴリズムのクラス階層として実装されている場合、戦略パターンが使えるよ。
アルゴリズムが、クライアントが知るべきではないデータを使う場合。複雑な、アルゴリズム関連のデータ構造を公開しないようにするために、戦略パターンが使えるんだ。
あるクラスが複数の振る舞いを定義していて、それがそのクラスの操作の中で複数の条件文の形として現れる場合。関連する条件分岐をそれぞれのStrategyクラスに移すことで、これらの条件文を置き換えることができるんだ。
例1
とある大型ショッピングモールがレジソフトウェアを開発したいんだって。ショッピングモールが時期によって出す割引やキャッシュバック(例えば、300元以上で100元バックとか)みたいな色々なプロモーションに対応できるようにしたいんだ。これを戦略パターンで実現してみるよ。設計したクラス図はこんな感じ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
| import java.util.*;
enum TYPE { NORMAL, CASH_DISCOUNT, CASH_RETURN};
interface CashSuper {
public double acceptCash(double money);
}
class CashNormal implements CashSuper { // 正常收费子类
public double acceptCash(double money) {
return money;
}
}
class CashDiscount implements CashSuper {
private double moneyDiscount; // 折扣率
public CashDiscount(double moneyDiscount) {
this moneyDiscount = moneyDiscount;
}
public double acceptCash(double money) {
return money* moneyDiscount;
}
}
class CashReturn implements CashSuper { // 满额返利
private double moneyCondition;
private double moneyReturn;
public CashReturn(double moneyCondition, double moneyReturn) {
this.moneyCondition = moneyCondition; // 满额数额
this.moneyReturn = moneyReturn; // 返利数额
}
public double acceptCash(double money) {
double result = money;
if(money >= moneyCondition )
result = money - Math.floor(money / moneyCondition) * moneyReturn;
return result;
}
}
class CashContext {
private CashSuper cs;
private TYPE t;
public CashContext(TYPE t) {
switch(t) {
case NORMAL: // 正常收费
cs = new CashNormal();
break;
case CASH_DISCOUNT: // 打8折
cs = new CashDiscount(0.8);
break;
case CASH_RETURN: // 满300返100
cs = new CashReturn(300, 100);
break;
}
}
public double GetResult(double money) {
return cs.acceptCash(money);
}
// 此处略去main()函数
}
|
例2
足し算、引き算、掛け算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
| public class StrategyPattern {
public static void main(String[] args) {
Strategy add = new AddStrategy();
Strategy subtraction = new SubtractionStrategy();
Strategy multiply = new MultiplyStrategy();
OperationContext context = new OperationContext(add);
context.Operation(1, 2);
context = new OperationContext(subtraction);
context.Operation(1, 2);
context = new OperationContext(multiply);
context.Operation(1, 2);
}
}
class OperationContext{
private Strategy strategy;
public OperationContext(Strategy strategy){
this.strategy = strategy;
}
public void Operation(int a, int b){
strategy.operation(a, b);
}
}
interface Strategy{
public void operation(int a, int b);
}
class AddStrategy implements Strategy{
@Override
public void operation(int a, int b){
System.out.println(a + b);
}
}
class SubtractionStrategy implements Strategy{
@Override
public void operation(int a, int b){
System.out.println(a - b);
}
}
class MultiplyStrategy implements Strategy{
@Override
public void operation(int a, int b){
System.out.println(a * b);
}
}
|