一,策略模式
策略模式:
- 定义算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户;
- 此算法把变化的代码从不变的代码中分离出来,针对接口编程而不是类(定义策略接口),通过组合/聚合方式使用策略;
二,原理类图
意图: 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
适用性:
许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时 ,可以使用策略模式。
算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。
三,实例
strategy
package com.neei.strategy;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/18 22:21
* @Description: 游学网
* @throws:
*/
public interface Strategy {
public Double count(Double pay);
}
CocreteStrategy
package com.neei.strategy;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/18 22:22
* @Description: 游学网
* @throws:
*/
public class StrategyNormal implements Strategy {
@Override
public Double count(Double pay) {
return pay ;
}
}
public class StrstegyPlatinum implements Strategy {
@Override
public Double count(Double pay) {
return pay * 0.98;
}
}
public class StrstegyDiamond implements Strategy {
@Override
public Double count(Double pay) {
return pay * 0.9;
}
}
context
package com.neei.strategy;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/18 22:24
* @Description: 游学网
* @throws:
*/
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public Double count(Double pay){
return strategy.count(pay);
}
}
调用
package com.neei.strategy;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/18 22:27
* @Description: 游学网
* @throws:
*/
public enum CustomerType {
NORMAL(0, "member"),
PLATINUM(1, "vip"),
DUAMOND(2, "vvip");
private int index;
private String message;
CustomerType(int index, String message) {
this.index = index;
this.message = message;
}
@Override
public String toString() {
return "CustomerType{" +
"index=" + this.index +
", message='" + this.message + '\'' +
'}';
}
}
public class StrategyFactory {
private static Map<CustomerType,Strategy> strstegyMap = new HashMap<CustomerType,Strategy>();
static {
strstegyMap.put(CustomerType.NORMAL ,new StrategyNormal());
strstegyMap.put(CustomerType.PLATINUM,new StrstegyPlatinum());
strstegyMap.put(CustomerType.DUAMOND,new StrstegyDiamond());
}
private StrategyFactory() {
}
public static Strategy getInstance(CustomerType type){
return strstegyMap.get(type);
}
}
package com.neei.strategy;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/18 22:30
* @Description: 游学网
* @throws:
*/
public class Client {
public static void main(String[] args) {
Double pay = 10000D;
Strategy strategyNormal = StrategyFactory.getInstance(CustomerType.NORMAL);
Context contextNormal = new Context(strategyNormal);
System.out.println(CustomerType.NORMAL.toString() + "应付:" + contextNormal.count(pay));
Strategy strategyPlatinum = StrategyFactory.getInstance(CustomerType.PLATINUM);
Context contextPlatinum = new Context(strategyPlatinum);
System.out.println(CustomerType.PLATINUM.toString() + "应付:" +contextPlatinum.count(pay));
Strategy strategyDuamond = StrategyFactory.getInstance(CustomerType.DUAMOND);
Context contextDuamond = new Context(strategyDuamond);
System.out.println(CustomerType.DUAMOND.toString() + "应付:"+contextDuamond.count(pay));
}
}
四,源码分析
JDK源码中使用的策略模式,如java.util.Arrays#sort(T[], java.util.Comparator<? super T>);
// Comparator<? super T> c 策略类
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}