策略模式 和 状态模式有点像,但是比状态模式稍微比较简单。
状态模式的状态之间是可以互相转换的,但是策略模式的策略之间是相互独立的。
策略模式 是把每个策略(解决问题的方法)独立成类,调用者只需要调用抽象策略,具体的实现策略以具体的情况而定。
策略的理解可以是一系列可以解决同一类问题的方法。
比如 小明去上班这个问题,策略可以有:走路、骑车、公交车、自驾,它们都可以解决 从 小明家 到 公司 这个问题。
下面以 网上购物付款 这个问题来说明策略模式
支付策略有:支付宝付款、微信付款、银联付款
支付接口(抽象的策略):
/**
* 支付接口
*/
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支付)。