策略模式 和 狀態模式有點像,但是比狀態模式稍微比較簡單。
狀態模式的狀態之間是可以互相轉換的,但是策略模式的策略之間是相互獨立的。
策略模式 是把每個策略(解決問題的方法)獨立成類,調用者只需要調用抽象策略,具體的實現策略以具體的情況而定。
策略的理解可以是一系列可以解決同一類問題的方法。
比如 小明去上班這個問題,策略可以有:走路、騎車、公交車、自駕,它們都可以解決 從 小明家 到 公司 這個問題。
下面以 網上購物付款 這個問題來說明策略模式
支付策略有:支付寶付款、微信付款、銀聯付款
支付接口(抽象的策略):
/**
* 支付接口
*/
public interface Pay {
/**
* 進行支付
*/
boolean doPay(double money);
}
支付寶支付 策略(具體策略1)
/**
* 支付實現類 支付寶支付
*/
public class AliPay implements Pay {
@Override
public boolean doPay(double money) {
System.out.println("使用支付寶支付 打95折 ");
money = money * 0.95;
System.out.println("實際消費 "+money +" 並且得到阿里積分 "+(money/10));
return false;
}
}
微信支付 策略(具體策略2)
/**
* 微信支付
*/
public class MicroPay implements Pay{
@Override
public boolean doPay(double money) {
System.out.println("使用微信支付 打98折");
money = money * 0.98;
System.out.println("實際消費 "+money);
return true;
}
}
銀聯支付 策略(具體策略3)
/**
* 銀聯支付策略
*/
public class BlankPay implements Pay {
@Override
public boolean doPay(double money) {
System.out.println("使用銀聯支付 打85折");
money = money * 0.85;
System.out.println("實際消費 "+money +" 並且得到銀聯積分 "+(money/1));
return true;
}
}
對外使用的策略(策略上下文Context)
使用 工廠方法 對支付類 進行實例。
構造函數 需要傳入支付方式
只暴露 doPay()供對外調用,使用者不需要關係具體是用什麼進行支付的
/**
* 支付的上下文
*/
public class PayHelp {
public static final int PAY_TYPE_ALI = 0;
public final int PAY_TYPE_MICRO = 1;
public final int PAY_TYPE_BLANK = 2;
//支付
private Pay pay;
/**
* 構造方法
*/
public PayHelp(int payType){
initPayType(payType);
}
/**
* 初始化 支付類型 用工廠方法進行實例
* @param payType
*/
public void initPayType(int payType){
switch (payType){
case PAY_TYPE_ALI:
pay = new AliPay();
break;
case PAY_TYPE_MICRO:
pay = new MicroPay();
break;
case PAY_TYPE_BLANK:
pay = new BlankPay();
break;
default:
pay = new AliPay();
}
}
/**
* 進行支付
*/
public boolean doPay(double money){
return pay.doPay(money);
}
}
測試類:
import java.util.Scanner;
public class StrategyTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String text = null;
System.out.println("請輸入結算方式(0支付寶 1 微信 2 銀聯):");
while ((text = scanner.next()) != null){
if(text.equals("0") || text.equals("1")||text.equals("2")){
PayHelp payHelp = new PayHelp(Integer.parseInt(text));
System.out.println("請輸入金額:");
double d = scanner.nextDouble();
payHelp.doPay(d);
System.out.println();
System.out.println("請輸入結算方式(0支付寶 1 微信 2 銀聯):");
}else {
System.out.println("結算方式輸入錯誤,請重新輸入(0支付寶 1 微信 2 銀聯):");
}
}
}
}
運行效果:
請輸入結算方式(0支付寶 1 微信 2 銀聯):
0
請輸入金額:
12.12
使用支付寶支付 打95折
實際消費 11.514 並且得到阿里積分 1.1514
請輸入結算方式(0支付寶 1 微信 2 銀聯):
1
請輸入金額:
23.12
使用微信支付 打98折
實際消費 22.657600000000002
請輸入結算方式(0支付寶 1 微信 2 銀聯):
2
請輸入金額:
76.09
使用銀聯支付 打85折
實際消費 64.6765 並且得到銀聯積分 64.6765
運行結果會根據具體選擇的結算方式來實例 Pay,如果這個時候多加了個 iphone支付,那麼只要再新增一個iphone支付的類以及把PayHelper()簡單改造下就可以了,不用去修改客戶端調用的方法(如果此客戶端不需要iphone支付)。