内容简介:定义了举例: 在一些外部网关,如银行网关设计时,因直连模式时会接入多个银行,这些银行的具体报文封装逻辑、解析逻辑、业务逻辑不同(多个类似行为的抽象,Context所依赖的接口
定义了 算法族 (一组行为),分别 封装 起来(封装实现),让他们之间可以 相互替换 (扩展),此模式让算法的 变化(扩展)独 立与使用算法的客户(解耦);
场景
- Strategy描述一组概念相同却行为不同(一个接口却实现不同)的相关类;
- Strategy的使用客户不应该知道其具体实现(解耦),避免暴露复杂的、与具体策略相关的数据结构;
- 一个类定义多种行为,避免这些行为以if-else的形式出现在此类中,减少对实现细节的依赖;
举例: 在一些外部网关,如银行网关设计时,因直连模式时会接入多个银行,这些银行的具体报文封装逻辑、解析逻辑、业务逻辑不同( 实现ConcreteStrategy ),但其都可抽象为共用的网关处理逻辑( 接口Strategy ); 为减少调用方对实现的依赖关系、便于接入其他银行、共用代码逻辑的复用 ,可采用策略模式进行设计;
结构
- Strategy
多个类似行为的抽象,Context所依赖的接口
- ConcreteStrategy
Strategy的具体实现,为Context提供具体逻辑实现
- Context
上下文(客户),一个具有多种行为的类,持有strategy引用
- 流程描述
Context 与Strategy关系为一对多,Strategy与ConcreteStrategy关系为一对多
推荐搭配
工厂模式、模板方法
代码实现
- 简单策略DEMO
测试代码
public class TransTest extends NnnToolsApplicationTests {
@Autowired
private Trans trans;
@Test
public void testTrans(){
TransDO transDO = new TransDO();
Invocation invocation = new Invocation();
invocation.setBizType("N00001");
invocation.setParam(transDO);
//调用,外部对内部无感知,无依赖
//Trans内部只依赖行为接口,不依赖实现,可动态改变其行为实现
trans.transfer(invocation);
}
}
复制代码
简单演示动态行为切换
/**
* @author hanlujun
*/
@Service
public class TransImpl implements Trans {
@Autowired
private Map<String,Validator> validators;
/**
* 交易操作
* @param var1
* @return
*/
@Override
public Result transfer(Invocation var1) {
//**变化的行为**
//获取对应业务类型的校验(如权限校验、非空校验、账户校验等)
Validator validator = validators.get(var1.getBizType());
if(Objects.nonNull(validator)){
//校验
validator.validation(var1.getParam());
}
//执行对应业务类型的业务逻辑
return accountOperation(var1).doTransfer(var1);
}
/**
* 测试
*/
public TransOperation accountOperation(Invocation var1){
// **变化的行为**
return SpringContextUtil.getBean(var1.getBizType(), TransOperation.class);
}
}
复制代码
- 进阶策略DEMO
借鉴之前老师的写法来演示并做了稍微改动,demo简单描述了策略模式是如何实现可复用、可扩展、可维护的OO思想;
另外此demo仍有很大的优化空间,需要大家发散思维;
测试代码
/**
* 测试
*/
public class TransTest extends NnnToolsApplicationTests {
@Autowired
private StrategyFactory strategyFactory;
public void testTrans(){
Context context = strategyFactory.makeDecision("N00001");
context.execute("N00001","{}");
}
}
复制代码
策略接口
/**
* 多个类似行为的抽象,Context所依赖的接口
*/
public interface IStrategy {
Response execute(String code, String jsonBody);
}
复制代码
策略接口与具体实现结合并结合模板方法
/**
* 多个类似行为的抽象,Context所依赖的接口,具体策略有子类实现
*/
@Slf4j
public abstract class AbstractStrategy implements IStrategy{
@Autowired
private Map<String, Validator> validators;
@Override
public Response execute(String code , String jsonBody) {
//获取对应业务类型的校验(如权限校验、非空校验、账户校验等)
Validator validator = validators.get(code);
if(Objects.nonNull(validator)){
//校验
validator.validation(jsonBody);
}
//执行对应业务类型的业务逻辑
return doTransfer(code);
}
/**
* 具体实现由子类决定
* @param code
* @return
*/
protected abstract Response doTransfer(String code);
}
复制代码
策略模式中的客户Context
/**
* 上下文(客户),一个具有多种行为的类,持有strategy引用
*/
public class Context {
private IStrategy strategy;
private Context(IStrategy strategy){
this.strategy = strategy;
}
public static Context getInstance(IStrategy strategy){
return new Context(strategy);
}
/**
* 执行策略
* @param code
* @param jsonBody
* @return
*/
public Response execute(String code, String jsonBody) {
return strategy.execute(code,jsonBody);
}
}
/**
* 策略工厂
*/
public interface IStrategyFactory {
Context makeDecision(String code);
}
复制代码
推荐搭配:工厂类
/**
* 策略工厂
*/
@Component
public class StrategyFactory implements IStrategyFactory {
@Override
public Context makeDecision(String code) {
String serviceName =BizTypeEnums.getServiceByCode(code);
IStrategy strategy = SpringContextUtil.getBean(serviceName);
return Context.getInstance(strategy);
}
}
复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Effective JavaScript
David Herman / Addison-Wesley Professional / 2012-12-6 / USD 39.99
"It's uncommon to have a programming language wonk who can speak in such comfortable and friendly language as David does. His walk through the syntax and semantics of JavaScript is both charming and h......一起来看看 《Effective JavaScript》 这本书的介绍吧!