Javaでのストラテジーデザインパターンの例についてのチュートリアル
ストラテジーデザインパターンは、行動的なデザインパターンの1つです。ストラテジーパターンは、特定のタスクに複数のアルゴリズムがある場合に使用され、クライアントは実際の実装を実行時に決定します。
戦略パターン
ストラテジーパターンはポリシーパターンとしても知られています。私たちは複数のアルゴリズムを定義し、クライアントアプリケーションに使用するアルゴリズムをパラメータとして渡すようにします。ストラテジーパターンの最も良い例の一つは、Comparatorパラメータを使用するCollections.sort()メソッドです。Comparatorインタフェースの異なる実装に基づいて、オブジェクトは異なる方法でソートされます。例として、シンプルなショッピングカートを実装してみましょう。ここでは、クレジットカードを使用する支払いストラテジーとPayPalを使用する支払いストラテジーの2つを持ちます。まず、支払い金額を引数として渡すためのストラテジーパターンのインタフェースを作成します。PaymentStrategy.java
package com.scdev.design.strategy;
public interface PaymentStrategy {
public void pay(int amount);
}
今後は、クレジットカード・デビットカードまたはPayPalを使用した支払いのためのアルゴリズムの具体的な実装を作成する必要があります。CreditCardStrategy.java
package com.scdev.design.strategy;
public class CreditCardStrategy implements PaymentStrategy {
private String name;
private String cardNumber;
private String cvv;
private String dateOfExpiry;
public CreditCardStrategy(String nm, String ccNum, String cvv, String expiryDate){
this.name=nm;
this.cardNumber=ccNum;
this.cvv=cvv;
this.dateOfExpiry=expiryDate;
}
@Override
public void pay(int amount) {
System.out.println(amount +" paid with credit/debit card");
}
}
PaypalStrategy.javaを日本語で述べると
package com.scdev.design.strategy;
public class PaypalStrategy implements PaymentStrategy {
private String emailId;
private String password;
public PaypalStrategy(String email, String pwd){
this.emailId=email;
this.password=pwd;
}
@Override
public void pay(int amount) {
System.out.println(amount + " paid using Paypal.");
}
}
私たちのストラテジーパターンの例のアルゴリズムはすでに準備完了です。ショッピングカートの実装および支払い方法は、支払いストラテジーとしての入力を必要とします。Item.java
package com.scdev.design.strategy;
public class Item {
private String upcCode;
private int price;
public Item(String upc, int cost){
this.upcCode=upc;
this.price=cost;
}
public String getUpcCode() {
return upcCode;
}
public int getPrice() {
return price;
}
}
ショッピングカート.java
package com.scdev.design.strategy;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
public class ShoppingCart {
//List of items
List<Item> items;
public ShoppingCart(){
this.items=new ArrayList<Item>();
}
public void addItem(Item item){
this.items.add(item);
}
public void removeItem(Item item){
this.items.remove(item);
}
public int calculateTotal(){
int sum = 0;
for(Item item : items){
sum += item.getPrice();
}
return sum;
}
public void pay(PaymentStrategy paymentMethod){
int amount = calculateTotal();
paymentMethod.pay(amount);
}
}
「ショッピングカートの支払い方法には支払いアルゴリズムが引数として必要であり、インスタンス変数として保管されていません」ということに注意してください。簡単なプログラムで、戦略パターンの例のセットアップをテストしましょう。「ShoppingCartTest.java」。
package com.scdev.design.strategy;
public class ShoppingCartTest {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
Item item1 = new Item("1234",10);
Item item2 = new Item("5678",40);
cart.addItem(item1);
cart.addItem(item2);
//pay by paypal
cart.pay(new PaypalStrategy("myemail@example.com", "mypwd"));
//pay by credit card
cart.pay(new CreditCardStrategy("Pankaj Kumar", "1234567890123456", "786", "12/15"));
}
}
上記のプログラムの出力は次のとおりです: [output]
50 paid using Paypal.
50 paid with credit/debit card
ストラテジーデザインパターンのクラス図
ストラテジーデザインパターンの重要なポイント
- We could have used composition to create instance variable for strategies but we should avoid that as we want the specific strategy to be applied for a particular task. Same is followed in Collections.sort() and Arrays.sort() method that take comparator as argument.
- Strategy Pattern is very similar to State Pattern. One of the difference is that Context contains state as instance variable and there can be multiple tasks whose implementation can be dependent on the state whereas in strategy pattern strategy is passed as argument to the method and context object doesn’t have any variable to store it.
- Strategy pattern is useful when we have multiple algorithms for specific task and we want our application to be flexible to chose any of the algorithm at runtime for specific task.
これでJavaにおけるストラテジーパターンに関しての説明は終わりです。お気に入りいただけたら嬉しいです。