注重代码规范的程序中,不允许出现 if-else 和 switch 分支较多的分支语句,否则产生大量的冗余代码、严重影响代码可读性。
针对不同分支获取不同的值。
例如,我们在对接其他平台时,a和b两个平台之间的某个对应字典的字典值定义不一致,需要进行转换:
/**
* a平台文件类型
*/
enum AFileType {
DOC("doc", "文档类型"),
PDF("pdf", "pdf类型"),
MP3("mp3", "mp3类型"),
MP4("mp4", "mp4类型");
private final String value;
private final String label;
PhysicalStatus(String value, String label) {
this.value = value;
this.label = label;
}
public String getValue() {
return this.value;
}
public String getLabel() {
return this.label;
}
}
/**
* b平台文件类型
*/
enum BFileType {
DOC("1", "文档类型"),
PDF("2", "pdf类型"),
MP3("3", "mp3类型"),
MP4("4", "mp4类型");
private final String value;
private final String label;
PhysicalStatus(String value, String label) {
this.value = value;
this.label = label;
}
public String getValue() {
return this.value;
}
public String getLabel() {
return this.label;
}
}
原分支语句:
/**
* b平台文件类型转换
*
* @param aFileType a平台文件类型
* @return b平台文件类型
*/
public String convertToBFileType(String aFileType){
if (StrUtil.equals(aFileType, AFileType.DOC.getValue())) {
return BFileType.DOC.getValue();
} else if (StrUtil.equals(aFileType, AFileType.PDF.getValue())) {
return BFileType.PDF.getValue();
} else if (StrUtil.equals(aFileType, AFileType.MP3.getValue())) {
return BFileType.MP3.getValue();
} else if (StrUtil.equals(aFileType, AFileType.MP4.getValue())) {
return BFileType.MP4.getValue();
} else {
return null;
}
}
这种为获取不同值的分支语句,一般采用枚举方案。
枚举改造如下:
/**
* A平台文件类型
*/
enum AFileType {
DOC("doc", "1", "文档类型"),
PDF("pdf", "2", "pdf类型"),
MP3("mp3", "3", "mp3类型"),
MP4("mp4", "4", "mp4类型");
private final String value;
private final String bValue;
private final String label;
PhysicalStatus(String value, String bValue, String label) {
this.value = value;
this.bValue = bValue;
this.label = label;
}
public String getValue() {
return this.value;
}
public String getBValue() {
return this.bValue;
}
public String getLabel() {
return this.label;
}
/**
* 转换为b平台文件类型
*/
public static String convertToBFileType(String value) {
for (BFileType bFileType : BFileType.values()) {
if (StrUtil.equals(bFileType.getAValue(), value)) {
return bFileType.getValue();
}
}
return null;
}
}
/**
* b平台文件类型
*/
enum BFileType {
DOC("1", "doc", "文档类型"),
PDF("2", "pdf", "pdf类型"),
MP3("3", "mp3", "mp3类型"),
MP4("4", "mp4", "mp4类型");
private final String value;
private final String aValue;
private final String label;
PhysicalStatus(String value, String aValue, String label) {
this.value = value;
this.aValue = aValue;
this.label = label;
}
public String getValue() {
return this.value;
}
public String getAValue() {
return this.aValue;
}
public String getLabel() {
return this.label;
}
/**
* 转换为a平台文件类型
*/
public static String convertToAFileType(String value) {
for (AFileType aFileType : AFileType.values()) {
if (StrUtil.equals(aFileType.getBValue(), value)) {
return aFileType.getvalue();
}
}
return null;
}
}
改造后的分支语句:
/**
* b平台文件类型转换
*
* @param aFileType a平台文件类型
* @return b平台文件类型
*/
public String convertToBFileType(String aFileType){
return AFileType.convertToBFileType(aFileType);
}
创建了类型的对应关系枚举,采用枚举 for 循环获取对应的枚举值。
针对不同分支执行不同的处理代码。不适于对象封装。
例如,根据不用的优惠券,采用不用的发放方式(轻量型,不适于对象封装):
/**
* 业务类
*/
@Service
@RequiredArgsConstructor
public class QueryGrantTypeService {
private final GrantTypeSerive grantTypeSerive;
private static Map<String, Function<String, String>> grantTypeMap = new HashMap<>();
/**
* 初始化业务分派逻辑
* key: 优惠券类型
* value: lambda表达式,最终会获得该优惠券的发放方式
*/
@PostConstruct
public void dispatcherInit(){
grantTypeMap.put("红包", resourceId -> grantTypeSerive.redPaper(resourceId));
grantTypeMap.put("购物券", resourceId -> grantTypeSerive.shopping(resourceId));
grantTypeMap.put("qq会员", resourceId -> grantTypeSerive.QQVip(resourceId));
}
public String getResult(String resourceType){
Function<String, String> function = getGrantTypeMap.get(resourceType); // 根据类型获取lambda表达式
if(result != null){
return function.apply(resourceId); // 向lambda表达式传入值并执行
}
return null;
}
}
针对不同分支执行不同的处理代码。适用于对象封装。
例如,根据不同的设备,选择对应的连接方法以及断开方法(设备适用于对象封装,且需要封装两个方法):
/**
* 统一分支业务处理接口
*/
public interface IDeviceHandler {
/**
* 连接设备
*/
void deviceConnect(Device device);
/**
* 断开设备
*/
void deviceDisConnect(Device device);
}
/**
* 统一分支业务处理器抽象类
*/
public abstract class AbstractDeviceHandler implements IDeviceHandler {
}
/**
* 处理器类001
*/
@Component("MC_001")
public class DeviceMc001Handler extends AbstractDeviceHandler {
/**
* 连接设备
*/
@Override
public void deviceConnect(Device device) {
// TODO 执行分支业务
}
/**
* 断开设备
*/
void deviceDisConnect(Device device) {
// TODO 执行分支业务
}
}
/**
* 处理器类002
*/
@Component("MC_002")
public class DeviceMc002Handler extends AbstractDeviceHandler {
/**
* 连接设备
*/
@Override
public void deviceConnect(Device device) {
// TODO 执行分支业务
}
/**
* 断开设备
*/
void deviceDisConnect(Device device) {
// TODO 执行分支业务
}
}
/**
* 业务类
*/
@Service
@RequiredArgsConstructor
public class DeviceService {
private final Map<String, IDeviceHandler> deviceHandlerMap; // 自动注入业务处理器map
/**
* 连接设备
*/
public void connect(Device device){
IDeviceHandler deviceHandler = deviceHandlerMap.get(device.getType()); // 获取对应的处理器
if (deviceHandler != null) {
deviceHandler.deviceConnect(device); // 调用对应处理器的方法
}
}
/**
* 断开设备
*/
public void disConnect(Device device){
IDeviceHandler deviceHandler = deviceHandlerMap.get(device.getType()); // 获取对应的处理器
if (deviceHandler != null) {
deviceHandler.deviceDisConnect(device); // 调用对应处理器的方法
}
}
}
分支语句的分支较多,或分支具有可扩展性,则建议使用方案来消除分支语句,避免代码臃肿、可读性低。
根据不同的场景,选择适用的方案: