状态模式的定义
一个对象在其内部状态改变的时候改变其行为
状态驱动,由上下文负责。代替if else 代替 switch case
普通方式
public String orderState(String state) {
if (state.equals("0")) {
return "已经发货";
}
if (state.equals("1")) {
return "正在运送中...调用第三方快递接口 展示 运送信息";
}
if (state.equals("2")) {
return "正在派送中... 返回派送人员信息";
}
if (state.equals("3")) {
return "已经签收,提示给用户快递员评价";
}
if (state.equals("4")) {
return "拒绝签收, 重新开始申请退单";
}
if (state.equals("5")) {
return "订单交易失败,调用短信接口提示 ";
}
return "未找到对应的状态";
}
}
状态模式uml图解如下:
代码实现如下:
上下文:
public class StatusContext {
private IOrderState iOrderState;
public StatusContext(IOrderState _iOrderState){
this.iOrderState = _iOrderState;
}
public void handleOrderByState(){
iOrderState.handleOrderByState();
}
}
接口:
public interface IOrderState {
void handleOrderByState();
}
实现
/**
* 已取消状态处理
*/
@Slf4j
@Service
public class CancelOrderStatusServiceImpl implements IOrderState {
@Override
public void handleOrderByState() {
log.info("已取消状态处理");
}
}
/**
* 已支付状态
*/
@Slf4j
@Service
public class YzfStatusOrderServiceImpl implements IOrderState {
@Override
public void handleOrderByState() {
//
log.info("已支付状态处理");
}
}
cilent调用:
public static void main(String[] args) {
// SpringApplication.run(DemoApplication.class, args);
StatusContext context = new StatusContext(new YzfStatusOrderServiceImpl());
context.handleOrderByState();
}
运行结果:
下一个问题就来了,如何知道具体是调用哪个实现类,这不还得写if else吗……
针对上一个问题,有个草率的解决方案,但是此方案并不怎么合适
public static void main(String[] args) {
Map<Integer, String> map = new HashMap();
map.put(1, "com.hyj.service.impl.stateOrder.YzfStatusOrderServiceImpl");
map.put(2, "com.hyj.service.impl.stateOrder.CancelOrderStatusServiceImpl");
IOrderState aa = null;
try {
aa = (IOrderState) Class.forName(map.get(1)).newInstance();//注意这里模拟假定1
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
StatusContext context = new StatusContext(aa);
context.handleOrderByState();
}
运行结果如上上图,结果正确。
还可以这样子实现,client代码如下图:
@RestController
@AllArgsConstructor
@RequestMapping("tbOrder")
public class TbOrderController {
private final ApplicationContext applicationContext;
@GetMapping("/updateStatus")
public void updateStatus(@RequestParam("serviceName") String serviceName){
IOrderState iOrderState = applicationContext.getBean(serviceName, IOrderState.class);
iOrderState.handleOrderByState();
}
}
结果正确,如下图:
上面这种方式,是利用了@service注入的serviceName为入参值,通过入参(注意首字母小写)
从上下文中找到符合的同名servie注入的实现类调用,@Service("aaa")可重命名,注意一定不能跟
别的service实现类重名。比较推荐这种方式。