策略模式是一种行为设计模式(behavioral design pattern). 通常用于执行含有多种算法的特定任务,在运行时决定用哪一种具体的策略实现.
介绍
策略模式(Strategy pattern)也可以被称为Policy Pattern. 我们定义多个策略算法的实现,让使用者把这些算法当做一个参数来传递
策略模式的一个很好的例子就是 Collections.sort() 方法,这个方法可以用Comparator作为参数。基于不同的Comparator接口实现,可以用不同的方式来进行排序
这儿我们举一个简单购物车的例子,有两种支付策略,使用信用卡 or 使用Paypal 首先我们创建一个接口,把支付金额作为参数。
PaymentStrategy.java
package com.journaldev.design.strategy;
public interface PaymentStrategy {
public void pay(int amount);
}
接下来,我们创建两种不同的支付实现,通过信用卡或者paypal来支付
CreditCardStrategy.java
package com.journaldev.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.journaldev.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.");
}
}
现在策略模式的例子已经准备好了,可以来实现购物车逻辑,在支付的方法把支付策略(PaymentStrategy)作为参数
Item.java
package com.journaldev.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;
}
}
ShoppingCart.java
package com.journaldev.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);
}
}
可以看到在购物车支付方法中使用了支付策略作为参数,并且没有保存把支付策略实例(这儿指PaymentStrategy的实例对象)
现在可以用一个简单的例子来测试策略模式 ShoppingCartTest.java
package com.journaldev.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"));
}
}
输出如下
50 paid using Paypal.
50 paid with credit/debit card
策略模式类图
重要点
-
可以使用组合的方式来创建不同的策略实例,但是要避免特定任务依赖特定策略(这儿说的是策略和任务要解耦)。可以看到 Collections.sort() and Arrays.sort() 使用相同comparator策略作为参数
-
策略模式和状态模式类似(State Pattern),一个不同点是,在状态模式中使用上下文中有状态实例变量,并且可以有多个任务的实现依赖于该状态。但在策略模式中,策略方法仅仅作为一个参数,在上线文中并不需要策略变量(oops~ 不知道咋翻译)
-
对于特定的任务有多个不同的实现时,策略模式往往很有用。应用程序在执行任务时可以灵活的来选择使用哪一种策略来完成任务
上面就是java中的策略模式,希望大家喜欢