状态模式涉及到的类有:
1.上下文,拥有一个或多个状态类实例,对客户端暴露接口;
2.状态接口,封装具体状态类所对应的行为;
3.具体状态类,真正实现状态行为。
类图如下:
代码示例:
先看一下之前同事写的代码:
@Override
public List getDrlOperationDTO(String typeId) {
List list = Operation.list;
List operationList = new ArrayList<>();
//字符串类型(等于,不等于,被包含于,不被包含于,不为空,为空,匹配,不匹配)
if (DataType.STR.getValue().toString().equals(typeId)) {
for (int i = 0; i < list.size(); i++) {
if (!list.get(i).getIndex().equals(Operation.GRE.getIndex())
&& !list.get(i).getIndex().equals(Operation.GREEQL.getIndex())
&& !list.get(i).getIndex().equals(Operation.LESS.getIndex())
&& !list.get(i).getIndex().equals(Operation.LESSEQL.getIndex())
&& !list.get(i).getIndex().equals(Operation.BET.getIndex())
&& !list.get(i).getIndex().equals(Operation.CONTAINS.getIndex())
&& !list.get(i).getIndex().equals(Operation.EXCLUDES.getIndex())) {
operationList.add(list.get(i));
}
}
//数值类型(等于,大于,大于等于,小于,小于等于,不等于,被包含于,不被包含于,不为空,为空)
} else if (DataType.INT.getValue().toString().equals(typeId) || DataType.FLOAT.getValue().toString().equals(typeId)
|| DataType.DOUBLE.getValue().toString().equals(typeId)) {
for (int i = 0; i < list.size(); i++) {
if (!list.get(i).getIndex().equals(Operation.MATCHES.getIndex())
&& !list.get(i).getIndex().equals(Operation.NMATCHES.getIndex())
&& !list.get(i).getIndex().equals(Operation.BET.getIndex())
&& !list.get(i).getIndex().equals(Operation.CONTAINS.getIndex())
&& !list.get(i).getIndex().equals(Operation.EXCLUDES.getIndex())){
operationList.add(list.get(i));
}
}
//布尔类型(等于,不等于,不为空,为空)
} else if (DataType.BOOLEAN.getValue().toString().equals(typeId)) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getIndex().equals(Operation.EQL.getIndex())
|| list.get(i).getIndex().equals(Operation.NEQL.getIndex())
|| list.get(i).getIndex().equals(Operation.NULL.getIndex())
|| list.get(i).getIndex().equals(Operation.NOTNULL.getIndex())){
operationList.add(list.get(i));
}
}
//数组类型(包含,不包含,不为空,为空)
} else if (DataType.STRS.getValue().toString().equals(typeId) || DataType.DOUBLES.getValue().toString().equals(typeId)
|| DataType.INTS.getValue().toString().equals(typeId)) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getIndex().equals(Operation.CONTAINS.getIndex())
|| list.get(i).getIndex().equals(Operation.EXCLUDES.getIndex())
|| list.get(i).getIndex().equals(Operation.NULL.getIndex())
|| list.get(i).getIndex().equals(Operation.NOTNULL.getIndex())){
operationList.add(list.get(i));
}
}
//其他类型为所有操作符
} else {
operationList = list;
}
return RuleAssembler.toDrlOperationDtos(operationList);
}
一堆if else看着就头疼,那么改成状态模式怎么做呢?
代码如下:
1.Context类
public class DrlOperatorContext {
private DrlOperatorState state;
private List operationList = new ArrayList<>();
public List getOperationList(){
return operationList;
}
public List addOperateList(String typeId) {
List list = Operation.list;
//字符串类型(等于,不等于,被包含于,不被包含于,不为空,为空,匹配,不匹配)
if (DataType.STR.getValue().toString().equals(typeId)) {
state = new DrlStrOperator();
//数值类型(等于,大于,大于等于,小于,小于等于,不等于,被包含于,不被包含于,不为空,为空)
} else if (DataType.INT.getValue().toString().equals(typeId) || DataType.FLOAT.getValue().toString().equals(typeId)
|| DataType.DOUBLE.getValue().toString().equals(typeId)) {
state = new DrlNumberOperator();
//布尔类型(等于,不等于,不为空,为空)
} else if (DataType.BOOLEAN.getValue().toString().equals(typeId)) {
state = new DrlBooleanOperator();
//数组类型(包含,不包含,不为空,为空)
} else if (DataType.STRS.getValue().toString().equals(typeId) || DataType.DOUBLES.getValue().toString().equals(typeId)
|| DataType.INTS.getValue().toString().equals(typeId)) {
state = new DrlArrayOperator();
//其他类型为所有操作符
} else {
operationList = list;
}
if (state != null) {
operationList = state.addOperateList(list, this);
}
return operationList;
}
}
2.State接口
public interface DrlOperatorState {
List addOperateList(List list, DrlOperatorContext context);
}
3.具体状态
public class DrlArrayOperator implements DrlOperatorState {
@Override
public List addOperateList(List list, DrlOperatorContext context) {
List operationList = context.getOperationList();
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getIndex().equals(Operation.CONTAINS.getIndex())
|| list.get(i).getIndex().equals(Operation.EXCLUDES.getIndex())
|| list.get(i).getIndex().equals(Operation.NULL.getIndex())
|| list.get(i).getIndex().equals(Operation.NOTNULL.getIndex())){
operationList.add(list.get(i));
}
}
return operationList;
}
}
public class DrlBooleanOperator implements DrlOperatorState{
@Override
public List addOperateList(List list, DrlOperatorContext context) {
List operationList = context.getOperationList();
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getIndex().equals(Operation.EQL.getIndex())
|| list.get(i).getIndex().equals(Operation.NEQL.getIndex())
|| list.get(i).getIndex().equals(Operation.NULL.getIndex())
|| list.get(i).getIndex().equals(Operation.NOTNULL.getIndex())){
operationList.add(list.get(i));
}
}
return operationList;
}
}
public class DrlNumberOperator implements DrlOperatorState {
@Override
public List addOperateList(List list, DrlOperatorContext context) {
List operationList = context.getOperationList();
for (int i = 0; i < list.size(); i++) {
if (!list.get(i).getIndex().equals(Operation.MATCHES.getIndex())
&& !list.get(i).getIndex().equals(Operation.NMATCHES.getIndex())
&& !list.get(i).getIndex().equals(Operation.BET.getIndex())
&& !list.get(i).getIndex().equals(Operation.CONTAINS.getIndex())
&& !list.get(i).getIndex().equals(Operation.EXCLUDES.getIndex())){
operationList.add(list.get(i));
}
}
return operationList;
}
}
public class DrlStrOperator implements DrlOperatorState {
@Override
public List addOperateList(List list, DrlOperatorContext context) {
List operationList = context.getOperationList();
for (int i = 0; i < list.size(); i++) {
if (!list.get(i).getIndex().equals(Operation.GRE.getIndex())
&& !list.get(i).getIndex().equals(Operation.GREEQL.getIndex())
&& !list.get(i).getIndex().equals(Operation.LESS.getIndex())
&& !list.get(i).getIndex().equals(Operation.LESSEQL.getIndex())
&& !list.get(i).getIndex().equals(Operation.BET.getIndex())
&& !list.get(i).getIndex().equals(Operation.CONTAINS.getIndex())
&& !list.get(i).getIndex().equals(Operation.EXCLUDES.getIndex())) {
operationList.add(list.get(i));
}
}
return operationList;
}
}
4.客户端调用
@Override
public List getDrlOperationDTO(String typeId) {
DrlOperatorContext context = new DrlOperatorContext();
List operationList = context.addOperateList(typeId);
return RuleAssembler.toDrlOperationDtos(operationList);
}
这样大大简化了,客户端的调用方式,提高了代码的也读性,同时需要增加新的类型只需要实现State接口即可。