行为型模式之策略模式介绍了策略模式的概念和用法,工作中可以借助枚举更加优雅的实现。
方法一:枚举+自动注入
一、建造枚举类
/**
* 策略方法枚举
*/
public enum EventEnum {
/**
* 用户新增事件
*/
USER_ADD_ORG("user_add_org","UserTypeAddService","用户新增事件"),
/**
* 用户更改
*/
USER_MODIFY_ORG("user_modify_org","UserModifyService","通讯录用户更改"),
public static EventEnum getValue(String eventType) {
for (EventEnum loginEnum : EventEnum.values()) {
if (loginEnum.getEventType().equals(eventType)) {
return loginEnum;
}
}
return null;
}
private String eventType;
private String serviceName;
private String desc;
EventEnum(String eventType, String serviceName, String desc) {
this.eventType = eventType;
this.serviceName = serviceName;
this.desc = desc;
}
}
二、编写策略接口
public interface EventTypeInterface {
/**
* @return
*/
String eventType();
}
// 用户修改实现类:
@Service("UserModifyService")
public class UserModifyService implements EventTypeInterface {
@Override
public String eventType() {
return "我是用户修改";
}
}
//用户新增实现类:
@Service("UserTypeAddService")
public class UserTypeAddService implements EventTypeInterface {
@Override
public String eventType() {
return "我是用户新增";
}
}
三、编写获取上下文方法类
@Service
public class EventSpringContext {
//Autowired自动注入EventTypeInterface实现类,key类名称
@Autowired
private final Map<String, EventTypeInterface> strategyMap = new ConcurrentHashMap<>(4);
/**
* 根据事件类型获取不同策略
* @param loginType
* @return
*/
public EventTypeInterface getService(String loginType) {
EventEnum eventEnum = EventEnum.getValue(loginType);
return strategyMap.get(eventEnum.getServiceName());
}
}
四、建立测试方法
@GetMapping("test1")
public String getTests(String eventType){
System.out.println("进来事件"+eventType);
EventTypeInterface service = eventSpringContext.getService(eventType);
String type= service.eventType();
System.out.println("返回结果"+eventType);
return eventType;
}
方法二:纯枚举
一、建造枚举类
package com.example.springbootdemo;
public enum ValidatorStrategy {
XML {
@Override
void doValidation(String content) {
System.out.println("This is a XML content");
}
},
JSON {
@Override
void doValidation(String content) {
System.out.println("This is a JSON content");
}
},
YAML {
@Override
void doValidation(String content) {
System.out.println("This is a YAML content");
}
},
CSV {
@Override
void doValidation(String content) {
System.out.println("This is a CSV content");
}
};
abstract void doValidation(String content);
}
二、编写获取上下文方法类
public class ValidatorContext {
private ValidatorStrategy strategy;
public ValidatorContext(ValidatorStrategy strategy) {
this.strategy = strategy;
}
public void runValidation(String content) {
strategy.doValidation(content);
}
}
三、建立测试方法
@GetMapping("test1")
public String getTests(String eventType){
ValidatorContext validator = new ValidatorContext(ValidatorStrategy.XML);
validator.runValidation("XML content");
}
方法三:枚举+工厂
一、建造枚举类
package com.ultiwill.strategy.enums;
import org.apache.commons.lang.StringUtils;
public enum PayEnumStrategy {
/**
* 阿里支付
*/
ALI_PAY("1","com.ultiwill.strategy.impl.AliPayStrategy"),
/**
* 微信支付
*/
WECHAT_PAY("2","com.ultiwill.strategy.impl.WeChatPayStrategy"),
/**
* 小米支付
*/
XIAOMI_PAY("3","com.ultiwill.strategy.impl.XiaomiPayStrategy");
private String code;
private String className;
PayEnumStrategy() {
}
PayEnumStrategy(String code, String className) {
this.code = code;
this.className = className;
}
public static String getClassNameByCode(String code) {
String className = "";
if (StringUtils.isEmpty(code)) {
return className;
}
for (PayEnumStrategy e : PayEnumStrategy.values()) {
if (e.code.equalsIgnoreCase(code)) {
className = e.className;
break;
}
}
return className;
}
}
二、编写策略接口
package com.ultiwill.strategy;
public interface PayStrategy {
/**
* 共同的行为方法
* @return
*/
String toPayHtml();
}
三种具体策略的实现 (阿里支付, 微信支付, 小米支付)
public class AliPayStrategy implements PayStrategy {
@Override
public String toPayHtml() {
return "调用阿里支付...AliPayStrategy";
}
}
public class WeChatPayStrategy implements PayStrategy {
@Override
public String toPayHtml() {
return "调用微信支付...WeChatPayStrategy";
}
}
public class XiaomiPayStrategy implements PayStrategy {
@Override
public String toPayHtml() {
return "调用小米支付...XiaomiPayStrategy";
}
}
三、编写策略工厂
package com.ultiwill.strategy.factory;
import com.ultiwill.strategy.PayStrategy;
import com.ultiwill.strategy.enums.PayEnumStrategy;
public class StrategyFactory {
/**
* 使用策略工厂获取具体策略实现
* @param code
* @return
*/
public static PayStrategy getPayStrategy(String code) {
try {
return (PayStrategy) Class.forName(PayEnumStrategy.getClassNameByCode(code)).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
四、编写获取上下文方法类
package com.ultiwill.strategy.context;
import com.ultiwill.strategy.PayStrategy;
import com.ultiwill.strategy.enums.PayEnumStrategy;
import com.ultiwill.strategy.factory.StrategyFactory;
import org.apache.commons.lang.StringUtils;
/**
* 上下文
*/
public class PayContextStrategy {
/**
* 获取具体的策略实现
*
* @param code
* @return
*/
public static String toPayHtml(String code) {
if (StringUtils.isBlank(code)) {
return "code不能为空...";
}
PayStrategy payStrategy = StrategyFactory.getPayStrategy(code);
if (payStrategy == null) {
return "没有找到具体的策略...";
}
return payStrategy.toPayHtml();
}
}
五、测试
@RestController
public class TestController {
@RequestMapping("/helloworld")
public String hello(String code) {
return PayContextStrategy.toPayHtml(code);
/*if ("0".equals(code)) {
return "调用阿里支付...AliPayStrategy";
} else if ("1".equals(code)) {
return "调用微信支付...AliPayStrategy";
} else if ("2".equals(code)) {
return "调用小米支付...AliPayStrategy";
}
return "调用接口不存在";
*/
}
}
总结:代码也是在进化的,最早用到的是第三种方式,但是很明显,使用工厂反射创建实现类一点也不优雅,现在已经很少用了。
第一种方法和第二种方法的区别就在是否在枚举中实现
最流行的还是第一种方式和第二种方式,区别是如果业务复杂,那还是要用接口单独实现,但是如果业务简单,比如一些字符串拼接,或者时间格式化,或者校验,那么就可以直接在枚举中实现。
网友评论