1. 模式简介
定义了一系列算法、分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户。可以避免多重分支的 if...else... 和 switch 语句。属于行为型设计模式。
2. 示例代码
- 支付方式策略
/**
* <p>
* 支付策略
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:43
*/
public enum PaymentStrategy {
/**
* 支付宝
*/
ALI_PAY,
/**
* 微信支付
*/
WECHAT_PAY,
/**
* 京东支付
*/
JD_PAY,
/**
* 银联支付
*/
UNION_PAY;
/**
* 支付方式容器池
*/
private static Map<PaymentStrategy, Payment> PAYMENT_POOL = new HashMap<>();
static {
PAYMENT_POOL.put(ALI_PAY, new AliPayment());
PAYMENT_POOL.put(WECHAT_PAY, new WeChatPayment());
PAYMENT_POOL.put(JD_PAY, new JdPayment());
PAYMENT_POOL.put(UNION_PAY, new UnionPayment());
}
/**
* 选择支付方式
*
* @param strategy 支付策略
* @return 支付方式
*/
public static Payment choose(PaymentStrategy strategy) {
Payment payment = PAYMENT_POOL.get(ALI_PAY);
if (PAYMENT_POOL.containsKey(strategy)) {
payment = PAYMENT_POOL.get(strategy);
}
System.out.println("欢迎使用: " + payment.channelName());
return payment;
}
}
- 支付方式的具体实现
/**
* <p>
* 支付接口
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:31
*/
public interface Payment {
/**
* 支付渠道
*
* @return 支付渠道
*/
String channelName();
/**
* 余额
*
* @return 账户余额
*/
double balance();
/**
* 支付金额
*
* @param money 金额
*/
void pay(double money);
}
/**
* <p>
* 支付宝支付
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:38
*/
public class AliPayment implements Payment {
/**
* 支付渠道
*
* @return 支付渠道
*/
@Override
public String channelName() {
return "支付宝支付";
}
/**
* 余额
*
* @return 账户余额
*/
@Override
public double balance() {
return 800;
}
/**
* 支付金额
*
* @param money 金额
*/
@Override
public void pay(double money) {
if (balance() < money) {
System.err.println("余额不足,当前余额:" + balance());
} else {
System.out.println("支付成功,交易金额:" + money);
}
}
}
/**
* <p>
* 京东支付
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:38
*/
public class JdPayment implements Payment {
/**
* 支付渠道
*
* @return 支付渠道
*/
@Override
public String channelName() {
return "京东支付";
}
/**
* 余额
*
* @return 账户余额
*/
@Override
public double balance() {
return 500;
}
/**
* 支付金额
*
* @param money 金额
*/
@Override
public void pay(double money) {
if (balance() < money) {
System.err.println("余额不足,当前余额:" + balance());
} else {
System.out.println("支付成功,交易金额:" + money);
}
}
}
/**
* <p>
* 微信支付
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:38
*/
public class WeChatPayment implements Payment {
/**
* 支付渠道
*
* @return 支付渠道
*/
@Override
public String channelName() {
return "微信支付";
}
/**
* 余额
*
* @return 账户余额
*/
@Override
public double balance() {
return 1234;
}
/**
* 支付金额
*
* @param money 金额
*/
@Override
public void pay(double money) {
if (balance() < money) {
System.err.println("余额不足,当前余额:" + balance());
} else {
System.out.println("支付成功,交易金额:" + money);
}
}
}
/**
* <p>
* 银联支付
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:38
*/
public class UnionPayment implements Payment {
/**
* 支付渠道
*
* @return 支付渠道
*/
@Override
public String channelName() {
return "银联支付";
}
/**
* 余额
*
* @return 账户余额
*/
@Override
public double balance() {
return 10;
}
/**
* 支付金额
*
* @param money 金额
*/
@Override
public void pay(double money) {
if (balance() < money) {
System.err.println("余额不足,当前余额:" + balance());
} else {
System.out.println("支付成功,交易金额:" + money);
}
}
}
- 测试类
/**
* <p>
* 策略模式,测试类
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:54
*/
public class PatternTest {
public static void main(String[] args) {
Payment payment = PaymentStrategy.choose(PaymentStrategy.ALI_PAY);
payment.pay(200);
System.out.println("--------------------");
payment = PaymentStrategy.choose(PaymentStrategy.UNION_PAY);
payment.pay(200);
}
}
- 测试结果
欢迎使用: 支付宝支付
支付成功,交易金额:200.0
--------------------
欢迎使用: 银联支付
余额不足,当前余额:10.0
3. UML 图例

4. 应用
// JDK 的 Comparator 接口,比如:
// java.util.Arrays#parallelSort(int[], int, int)
// java.util.TreeMap#TreeMap(java.util.Comparator<? super K>)
// Spring 的 Resource 接口,比如:
// ClassPathResource
// UrlResource
// FileUrlResource
// FileSystemResource
// ClassPathResource
// ByteArrayResource
// InputStreamResource
5. 场景
- 假如系统中有很多类,而他们的区别仅仅在于他们的行为不同。
- 一个系统需要动态地在几种算法中选择一种。
6. 优缺点
优点: 1、策略模式符合开闭原则。2、避免使用多重条件转移语句,如if…else…语句、switch语句。3、使用策略模式可以提高算法的保密性和安全性。
缺点: 1、客户端必须知道所有的策略,并且自行决定使用哪一个策略类。 2、代码中会产生非常多策略类,增加维护难度。