定义:策略模式也称政策模式,它是将定义的算法家族分别封装起来,让它们之间可以相互替换,从而让算法的变化不会影响到使用算法的用户。可以避免多重分支if-else和switch语句。
适用场景:
1. 假如系统中有很多类,而他们的区别仅仅在于他们的行为不同。
2. 一个系统需要动态地在几种算法中选择一种。
3. 需要屏蔽算法规则。
上周刚好遇到这种大量if-else的业务场景,业务场景如下:
我们项目是一个一体化的工程,也就是各个上游业务系统会把单据全部根据接口推到我们的项目中,有一个状态跟踪的接口,就是根据上游传的业务类型,和状态值,要更新对应业务单据的状态值,上一个开发人员就是通过大量的if-else来进行处理,代码大概如下:
/**
* 枚举所有业务类型
*/
public enum BusinessType {
PLAN_ORDER("plan_order", "计划订单"),
TRADE_ORDER("trade_order", "交易订单"),
FEE_ORDER("fee_order", "费用订单"),
OTHER_FEE_ORDER("other_fee_order", "其他费用订单");
BusinessType(String code, String name) {
this.code = code;
this.name = name;
}
private String code;
private String name;
public String getCode() {
return code;
}
public String getName() {
return name;
}
}
/**
* 业务处理类
*/
public class FellowStatus {
public void fellowStatus(String businessType, String status){
if(businessType.equals(BusinessType.FEE_ORDER.getCode())){
System.out.println("费用订单相关处理,更改状态为:" + status);
}else if(businessType.equals(BusinessType.OTHER_FEE_ORDER.getCode())){
System.out.println("其他费用订单相关处理,更改状态为:" + status);
}else if(businessType.equals(BusinessType.PLAN_ORDER.getCode())){
System.out.println("计划订单相关处理,更改状态为:" + status);
}else if(businessType.equals(BusinessType.TRADE_ORDER.getCode())){
System.out.println("交易订单相关处理,更改状态为:" + status);
}else{
System.out.println("业务类型错误,状态为:" + status);
}
}
}
public class Client {
public static void main(String[] args) {
FellowStatus fellowStatus = new FellowStatus();
fellowStatus.fellowStatus("fee_order", "1");
}
}
然后通过临时学习策略模式后,修改代码:
/**
* 业务类型接口
*/
public interface IbusinessType {
void statusFellow(String businessType, String stauts);
}
public class FeeOrder implements IbusinessType {
public void statusFellow(String businessType, String stauts) {
System.out.println("费用订单更改状态为:" + stauts);
}
}
public class OtherFeeOrder implements IbusinessType {
public void statusFellow(String businessType, String stauts) {
System.out.println("其他费用订单更改状态为:" + stauts);
}
}
public class PlanOrder implements IbusinessType {
public void statusFellow(String businessType, String stauts) {
System.out.println("计划订单更改状态为:" + stauts);
}
}
public class TradeOrder implements IbusinessType {
public void statusFellow(String businessType, String stauts) {
System.out.println("交易订单更改状态为:" + stauts);
}
}
public class BusinessTypeFactory {
public static IbusinessType getBusinessType(String businessType){
IbusinessType ibusinessType = null;
try {
Class<?> aClass = Class.forName(PackageName.packageName + businessType);
ibusinessType = (IbusinessType)aClass.newInstance();
} catch (Exception e) {
System.out.println("该业务类型不存在!");
}
return ibusinessType;
}
}
/**
* 记录完全路径名,因为用的反射
*/
public class PackageName {
public static String packageName = "com.gupaoedu.vip.pattern.bridge.strategy.V2.";
}
public class Client {
public static void main(String[] args) {
String businessType = "FeeOrder";
String status = "1";
IbusinessType businessTypePojo = BusinessTypeFactory.getBusinessType(businessType);
businessTypePojo.statusFellow(businessType, status);
}
}
然后昨天晚上上课后,再次修改代码,但是感觉,这样改之后,每次启动就会把所有的业务类型类给初始化,改动的代码:
public class BusinessTypeFactory {
private static Map<String, IbusinessType> map = new HashMap<String, IbusinessType>();
static {
map.put(BusinessType.FEE_ORDER.getCode(), new FeeOrder());
map.put(BusinessType.OTHER_FEE_ORDER.getCode(), new OtherFeeOrder());
map.put(BusinessType.TRADE_ORDER.getCode(), new TradeOrder());
map.put(BusinessType.PLAN_ORDER.getCode(), new PlanOrder());
}
public static IbusinessType getBusinessType(String businessType) throws Exception {
if (!map.containsKey(businessType)) {
throw new Exception("当前业务类型不存在!");
}
IbusinessType ibusinessType = map.get(businessType);
return ibusinessType;
}
}
public class Client {
public static void main(String[] args) {
String businessType = "fee_order";
String status = "1";
IbusinessType businessTypePojo = null;
try {
businessTypePojo = BusinessTypeFactory.getBusinessType(businessType);
} catch (Exception e) {
e.printStackTrace();
}
businessTypePojo.statusFellow(businessType, status);
}
}
优点:
1. 符合开闭原则
2. 避免适用多重条件转移语句,如:if-else 和 switch语句
3. 提高算法的保密性和安全性
缺点:
1. 客户必须知道所有策略,并且自行决定使用哪一种策略
2. 代码中会产生非常多策略类,增加维护难度