策略模式的实际实现
2020-12-07 本文已影响0人
帮我的鸵鸟盖个章
现在有一个添加售后单的 操作,根据售后的类型分为:维修,退款,补发,换新等。
使用策略模式,能避免使用大量的if else
,不用频繁的去做判断,代码也会显得比较简洁,逻辑清晰。
这里使用抽象类和接口结合的方法,类似于策略模式,对于该类似场景,非常适用。
步骤如下:
- 定义售后类型枚举;
- 定义接口类,定义添加方法;
- 定义抽象类,实现上面的接口;
- 抽象类定义枚举,对应实现类
serviceName
; - 定义
get()
方法,根据枚举返回对应的实现类;(此处为实际实现类); - 定义公共方法接口(数据检查);
- 抽象类定义枚举,对应实现类
- 根据售后类型,定义若干实现类,继承上面的抽象类;
- 实现抽象类的公共方法接口
- 实现接口定义的添加方法
demo
接口
import com.aftersale.constant.AfterSaleAddTypeEnum;
public interface IAddAfterSaleRegisterService {
public Boolean addAfterSale(AfterSaleAddTypeEnum addTypeEnum);
}
抽象类
import com.aftersale.constant.AfterSaleAddTypeEnum;
import com.aftersale.service.IAddAfterSaleRegisterService;
import com.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.*;
@Slf4j
public abstract class AbstractAddAfterSaleRegisterService implements IAddAfterSaleRegisterService {
// 这个引入很重要
@Autowired
private Map<String, AbstractAddAfterSaleRegisterService> map;
/**
* 枚举: 增加类型-服务名称
*/
private enum AddTypeServiceName {
/**
* 维修
*/
REPAIR(AfterSaleAddTypeEnum.REPAIR, "addRepairService"),
/**
* 补发
*/
REISSUE(AfterSaleAddTypeEnum.REPAIR, "addReissueService"),
;
public AfterSaleAddTypeEnum addTypeEnum;
public String serviceName;
private AddTypeServiceName(AfterSaleAddTypeEnum addTypeEnum, String serviceName) {
this.addTypeEnum = addTypeEnum;
this.serviceName = serviceName;
}
public static AddTypeServiceName with(AfterSaleAddTypeEnum addTypeEnum) {
if (null == addTypeEnum) {
return null;
}
for (AddTypeServiceName m : AddTypeServiceName.values()) {
if (m.addTypeEnum.equals(addTypeEnum)) {
return m;
}
}
return null;
}
}
private AbstractAddAfterSaleRegisterService getService(AfterSaleAddTypeEnum addTypeEnum) {
AddTypeServiceName serviceNameEnum = AddTypeServiceName.with(addTypeEnum);
if (null == serviceNameEnum) {
log.error(String.format("不支持的售后登记添加类型[%s]", addTypeEnum.getCode()));
throw ServiceException.build(String.format("不支持的售后登记添加类型[%s]", addTypeEnum.getCode()));
}
AbstractAddAfterSaleRegisterService service = this.map.get(serviceNameEnum.serviceName);
if (null == service) {
log.error(String.format("不支持的服务[%s]", serviceNameEnum.serviceName));
throw ServiceException.build(String.format("不支持的服务[%s]", serviceNameEnum.serviceName));
}
return service;
}
/**
* 登记前数据检查
* @param addTypeEnum
* @return
*/
public abstract Boolean checkBeforeAdd(AfterSaleAddTypeEnum addTypeEnum);
/**
* 添加
* @param addTypeEnum
* @return
*/
public abstract Boolean add(AfterSaleAddTypeEnum addTypeEnum);
@Override
public Boolean addAfterSale(AfterSaleAddTypeEnum addTypeEnum) {
Boolean checkResult = this.getService(addTypeEnum).checkBeforeAdd(addTypeEnum);
if (checkResult){
return this.getService(addTypeEnum).add(addTypeEnum);
}
return true;
}
}
实现类
@Primary默认实现
这个默认实现,是写了一个实际售后的类型之外的情况,默认抛出错误。
结合抽象类的。由于有多个类都实现了接口,spring不知道注入哪一个,所以@primary的作用就是告诉spring,优先考虑注入哪一个。
@Autowired
private Map<String, AbstractAddAfterSaleRegisterService> map;
使用。这个地方需要自己理解哦~
import com.aftersale.constant.AfterSaleAddTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
@Service("deafultRepairService")
@Primary
@Slf4j
public class DefaultRepairServiceImpl extends AbstractAddAfterSaleRegisterService {
@Override
public Boolean checkBeforeAdd(AfterSaleAddTypeEnum addTypeEnum) {
log.error("无法识别的售后登记类型");
return false;
}
@Override
public Boolean add(AfterSaleAddTypeEnum addTypeEnum) {
log.error("无法识别的售后登记类型");
return false;
}
}
具体实现1
import com.aftersale.constant.AfterSaleAddTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service("addReissueService")
@Slf4j
public class AddReissueServiceImpl extends AbstractAddAfterSaleRegisterService {
@Override
public Boolean checkBeforeAdd(AfterSaleAddTypeEnum addTypeEnum) {
log.info("xxx");
return true;
}
@Override
public Boolean add(AfterSaleAddTypeEnum addTypeEnum) {
log.info("xxx");
return true;
}
}
具体实现2
import com.aftersale.constant.AfterSaleAddTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service("addRepairService")
@Slf4j
public class AddRepairServiceImpl extends AbstractAddAfterSaleRegisterService {
@Override
public Boolean checkBeforeAdd(AfterSaleAddTypeEnum addTypeEnum) {
log.info("xxx");
return true;
}
@Override
public Boolean add(AfterSaleAddTypeEnum addTypeEnum) {
log.info("xxx");
return true;
}
}
具体使用时,只需要正常的注入接口即可。