策略模式
- 一、策略模式的概念与角色
- 二、策略模式的应用场景
- 三、策略模式的通用写法
- 四、策略模式的支付案例代码示例
- 五、策略模式在源码中的应用
- 六、策略模式的优缺点
- 七、设计模式的相关博客文章链接
- 1、七大设计原则的简单解释(包含合成复用原则),简单理解、快速入门,具备案例代码
- 2、工厂模式详解附有代码案例分析(简单工厂,工厂方法,抽象工厂)
- 3、单例模式详解及代码案例与应用场景(饿汉式单例模式、懒汉式单例模式、注册式单例模式)
- 4、原型模式详解附有代码案例分析(浅克隆和深克隆的相关解析)
- 5、建造者模式详解附有代码案例分析(包含建造者模式与工厂模式的区别分析)
- 6、门面模式详解附有代码案例分析
- 7、装饰者模式详解附有代码案例分析
- 8、享元模式详解附有代码案例分析(包含享元模式的源码应用分析——String中的享元模式应用、Integer中的享元模式应用)
- 9、组合模式详解附有代码案例分析(包含透明组合模式、安全组合模式的代码示例)
- 10、桥接模式详解附有代码案例分析
- 11、适配器模式详解附有代码案例分析(包含类适配器、对象适配器以及接口适配器的代码示例)
- 12、委派模式详解附有代码案例分析(包含委派模式在JDK中的源码示例解析)
- 13、模板方法模式详解附有代码案例分析(包含模板方法模式重构JDBC操作业务代码示例)
- 14、策略模式详解附有代码案例分析(包含策略模式在源码中的应用以及代码示例)
- 15、责任链模式详解附有代码案例分析(包含责任链模式与建造者模式的结合代码案例)
- 16、迭代器模式详解附有代码案例分析(包含迭代器模式的源码应用分析)
- 17、命令模式详解附有代码案例分析(包含命令模式的源码应用分析)
- 18、状态模式详解附有代码案例分析(包含状态模式与其他相关设计模式的对比)
- 19、备忘录模式详解附有代码案例分析
- 20、中介者模式详解附有代码案例分析
- 21、解释器模式详解附有代码案例分析
- 22、观察者模式详解附有代码案例分析(包含观察者模式使用JDK方式实现)
- 23、访问者模式详解附有代码案例分析
一、策略模式的概念与角色
(一)、策略模式的概念
策略模式又叫做政策模式,它是将 定义的算法家族、分别封装起来,让他们之间可以互相替换,从而让算法的变化不会影响到使用算法的用户。属于行为型模式。
策略模式使用的就是面向对象的继承和多态机制,从而实现统一行为在不同场景下具备不同实现。
(二)、策略模式的角色
1、上下文角色(Context):用来操作策略的上下文环境,屏蔽高层模块(客户端)对策略,算法的直接访问,封装可能存在的变化。
2、抽象策略角色(Strategy):规定策略或算法的行为。
3、具体策略角色(ConcreteStategy):具体的策略或算法实现。
二、策略模式的应用场景
1、针对同一类型问题,有多种处理方式,每一种都能独立解决问题。
2、算法需要自由切换场景。
3、需要屏蔽算法规则的场景。
三、策略模式的通用写法
抽象策略类:Strategy
public interface Strategy {
void algorithm();
}
具体策略类:ConcreteStrategyA
public class ConcreteStrategyA implements Strategy {
@Override
public void algorithm() {
System.out.println("Strategy A");
}
}
具体策略类:ConcreteStrategyB
public class ConcreteStrategyB implements Strategy {
@Override
public void algorithm() {
System.out.println("Strategy B");
}
}
上下文:Context
public class Context {
private Strategy mStrategy;
public Context(Strategy strategy) {
this.mStrategy = strategy;
}
public void algorithm() {
this.mStrategy.algorithm();
}
}
测试类:
public class Test {
public static void main(String[] args) {
//选择一个具体策略
Strategy strategy = new ConcreteStrategyA();
//来一个上下文环境
Context context = new Context(strategy);
//客户端直接让上下文环境执行算法
context.algorithm();
}
}
四、策略模式的支付案例代码示例
MsgResult:
public class MsgResult {
private int code;
private Object data;
private String msg;
public MsgResult(int code, Object data, String msg) {
this.code = code;
this.data = data;
this.msg = msg;
}
@Override
public String toString() {
return "MsgResult{" +
"code=" + code +
", data=" + data +
", msg='" + msg + '\'' +
'}';
}
}
Payment:
public abstract class Payment {
public abstract String getName();
public MsgResult pay(String uid, double amount) {
if (queryBalance(uid) < amount) {
return new MsgResult(500, "支付失败", "余额不足");
}
return new MsgResult(200, "支付成功", "交易成功,交易金额:" + amount);
}
protected abstract double queryBalance(String uid);
}
AliPay:
public class AliPay extends Payment {
@Override
public String getName() {
return "支付宝";
}
@Override
protected double queryBalance(String uid) {
return 520;
}
}
JdPay:
public class JdPay extends Payment {
@Override
public String getName() {
return "京东支付";
}
@Override
protected double queryBalance(String uid) {
return 123;
}
}
WeChatPay:
public class WeChatPay extends Payment {
@Override
public String getName() {
return "微信支付";
}
@Override
protected double queryBalance(String uid) {
return 250;
}
}
PayStrategy:
public class PayStrategy {
public static final String ALI_PAY = "AliPay";
public static final String JD_PAY = "JdPay";
public static final String WECHAT_PAY = "WeChatPay";
public static final String DEFAULT_PAY = "WeChatPay";
private static Map<String, Payment> strategy = new HashMap<String, Payment>();
static {
strategy.put(ALI_PAY, new AliPay());
strategy.put(JD_PAY, new JdPay());
strategy.put(WECHAT_PAY, new WeChatPay());
}
public static Payment get(String payKey) {
if (!strategy.containsKey(payKey)) {
return strategy.get(DEFAULT_PAY);
}
return strategy.get(payKey);
}
}
Order:
public class Order {
private String uid;
private String orderId;
private double amount;
public Order(String uid, String orderId, double amount) {
this.uid = uid;
this.orderId = orderId;
this.amount = amount;
}
public MsgResult pay() {
return pay(PayStrategy.DEFAULT_PAY);
}
public MsgResult pay(String payKey) {
Payment payment = PayStrategy.get(payKey);
System.out.println("本次交易使用:" + payment.getName());
System.out.println("交易金额:" + amount);
return payment.pay(uid, amount);
}
}
测试类:
public class Test {
public static void main(String[] args) {
Order order = new Order("123", "234345345", 234);
System.out.println(order.pay(PayStrategy.WECHAT_PAY));
}
}
类图:
五、策略模式在源码中的应用
比较器:Comparator接口——compare()方法就是一个策略抽象实现
public interface Comparator<T> {
// ......省略中间代码
int compare(T o1, T o2);
Arrays类中的parallelSort()方法边将Comparator作为参数传入作为排序策略
public class Arrays {
// ...... 省略中间代码
public static <T> void parallelSort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> cmp) {
rangeCheck(a.length, fromIndex, toIndex);
if (cmp == null)
cmp = Arrays.NaturalOrder.INSTANCE;
int n = toIndex - fromIndex, p, g;
if (n <= MIN_ARRAY_SORT_GRAN ||
(p = ForkJoinPool.getCommonPoolParallelism()) == 1)
TimSort.sort(a, fromIndex, toIndex, cmp, null, 0, 0);
else
new ArraysParallelSortHelpers.FJObject.Sorter<T>
(null, a,
(T[]) Array.newInstance(a.getClass().getComponentType(), n),
fromIndex, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
MIN_ARRAY_SORT_GRAN : g, cmp).invoke();
}
// ...... 省略中间代码
}
在TreeMap的构造方法中同样使用了
public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable,
// ...... 省略中间代码
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
// ...... 省略中间代码
}
六、策略模式的优缺点
(一)、优点
1、策略模式符合开闭原则
2、避免使用多重条件转移语句,例如:if…else…
3、使用策略模式可以提高算法的保密性和安全性
(二)、缺点
1、客户端必须知道所有的策略,并且自行决定使用哪一个策略类
2、代码中会尝试非常多的策略类,增加维护难度
七、设计模式的相关博客文章链接
1、七大设计原则的简单解释(包含合成复用原则),简单理解、快速入门,具备案例代码
链接: 七大设计原则的简单解释(包含合成复用原则),简单理解、快速入门,具备案例代码.
2、工厂模式详解附有代码案例分析(简单工厂,工厂方法,抽象工厂)
链接: 工厂模式详解附有代码案例分析(简单工厂,工厂方法,抽象工厂).
3、单例模式详解及代码案例与应用场景(饿汉式单例模式、懒汉式单例模式、注册式单例模式)
链接: 单例模式详解及代码案例与应用场景(饿汉式单例模式、懒汉式单例模式、注册式单例模式).
4、原型模式详解附有代码案例分析(浅克隆和深克隆的相关解析)
链接: 原型模式详解附有代码案例分析(浅克隆和深克隆的相关解析).
5、建造者模式详解附有代码案例分析(包含建造者模式与工厂模式的区别分析)
链接: 建造者模式详解附有代码案例分析(包含建造者模式与工厂模式的区别分析).
6、门面模式详解附有代码案例分析
链接: 门面模式详解附有代码案例分析.
7、装饰者模式详解附有代码案例分析
链接: 装饰者模式详解附有代码案例分析.
8、享元模式详解附有代码案例分析(包含享元模式的源码应用分析——String中的享元模式应用、Integer中的享元模式应用)
链接: 享元模式详解附有代码案例分析(包含享元模式的源码应用分析——String中的享元模式应用、Integer中的享元模式应用).
9、组合模式详解附有代码案例分析(包含透明组合模式、安全组合模式的代码示例)
链接: 组合模式详解附有代码案例分析(包含透明组合模式、安全组合模式的代码示例).
10、桥接模式详解附有代码案例分析
链接: 桥接模式详解附有代码案例分析.
11、适配器模式详解附有代码案例分析(包含类适配器、对象适配器以及接口适配器的代码示例)
链接: 适配器模式详解附有代码案例分析(包含类适配器、对象适配器以及接口适配器的代码示例).
12、委派模式详解附有代码案例分析(包含委派模式在JDK中的源码示例解析)
链接: 委派模式详解附有代码案例分析(包含委派模式在JDK中的源码示例解析).
13、模板方法模式详解附有代码案例分析(包含模板方法模式重构JDBC操作业务代码示例)
链接: 模板方法模式详解附有代码案例分析(包含模板方法模式重构JDBC操作业务代码示例).
14、策略模式详解附有代码案例分析(包含策略模式在源码中的应用以及代码示例)
链接: 策略模式详解附有代码案例分析(包含策略模式在源码中的应用以及代码示例).
15、责任链模式详解附有代码案例分析(包含责任链模式与建造者模式的结合代码案例)
链接: 责任链模式详解附有代码案例分析(包含责任链模式与建造者模式的结合代码案例).
16、迭代器模式详解附有代码案例分析(包含迭代器模式的源码应用分析)
链接: 迭代器模式详解附有代码案例分析(包含迭代器模式的源码应用分析).
17、命令模式详解附有代码案例分析(包含命令模式的源码应用分析)
链接: 命令模式详解附有代码案例分析(包含命令模式的源码应用分析).
18、状态模式详解附有代码案例分析(包含状态模式与其他相关设计模式的对比)
链接: 状态模式详解附有代码案例分析(包含状态模式与其他相关设计模式的对比).
19、备忘录模式详解附有代码案例分析
链接: 备忘录模式详解附有代码案例分析.
20、中介者模式详解附有代码案例分析
链接: 中介者模式详解附有代码案例分析.
21、解释器模式详解附有代码案例分析
链接: 解释器模式详解附有代码案例分析.
22、观察者模式详解附有代码案例分析(包含观察者模式使用JDK方式实现)
链接: 观察者模式详解附有代码案例分析(包含观察者模式使用JDK方式实现).
23、访问者模式详解附有代码案例分析
链接: 访问者模式详解附有代码案例分析.