一、策略模式
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
二、介绍
- 意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
- 主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
- 何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
- 如何解决:将这些算法封装成一个一个的类,任意地替换。
- 关键代码:实现同一个接口。
- 应用实例:
-
- 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。
-
- 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
-
- 3、JAVA AWT 中的 LayoutManager。
- 优点:
-
- 1、算法可以自由切换。
-
- 2、避免使用多重条件判断。
-
- 3、扩展性良好。
- 缺点:
-
- 1、策略类会增多。
-
- 2、所有策略类都需要对外暴露。
- 使用场景:
-
- 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
-
- 2、一个系统需要动态地在几种算法中选择一种。
-
- 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
- 注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
三、列表工具类
1、对两个列表去重并合并。
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.stream.Collectors;
/**
* <code>Details determine success.</code>
* by Liang ZC., Phd@Stanford
*
* @author LIANGZHICHENG
* @date 2019-7-10 15:46
* @see http://www.stanford.edu
*/
public class ListUtils {
/**
* {@param srcList} join {@param joinList} and the {@param srcList} will be distincted.
*
* @param srcList
* @param joinList
*/
public static <T> void joinAndDistinct(List<T> srcList,
List<T> joinList) {
if (CollectionUtils.isEmpty(srcList) && CollectionUtils.isEmpty(joinList)) {
return;
}
LinkedHashSet tmpSet = Sets.newLinkedHashSet();
tmpSet.addAll(srcList);
if (CollectionUtils.isNotEmpty(joinList)) {
tmpSet.addAll(joinList);
}
srcList.clear();
srcList.addAll(tmpSet);
}
/**
* Union two list and distinct .
*
* @param list1
* @param list2
* @param <T>
* @return
*/
public static <T> List<T> unionAndDistinct(List<T> list1,
List<T> list2) {
return org.apache.commons.collections4.ListUtils
.union(list1, list2)
.stream()
.distinct()
.collect(Collectors.toList());
}
}
四、使用枚举类实现策略模式
import com.google.common.collect.ImmutableMap;
import com.pingan.lcloud.ai.knowledgeBase.v2.common.ListUtils;
import com.pingan.lcloud.ai.knowledgeBase.v2.common.enums.FaqStepEnum;
import com.pingan.lcloud.ark.log.LoggerUtil;
import java.lang.annotation.Native;
import java.util.*;
/**
* <code>Details determine success.</code>
* by Liang ZC., Phd@Stanford
*
* @author LIANGZHICHENG
* @date 2019-8-18 13:56
* @see http://www.stanford.edu
*/
public enum StepEnum {
/*
* N777777777NO
* N7777777777777N
* M777777777777777N
* *N877777777D77777M
* N M77777777ONND777M
* MN777777777NN D777
* N7ZN777777777NN ~M7778
* N777777777777MMNN88777N
* N777777777777MNZZZ7777O
* DZN7777O77777777777777
* N7OONND7777777D77777N
* 8*M++++?N???$77777$
* M7++++N+M77777777N
* N77O777777777777$ M
* DNNM$$$$777777N D
* N*N:=N$777N7777M NZ
* 77Z::::N777777777 ODZZZ
* 77N::::::N77777777M NNZZZ$
* $777:::::::77777777MN ZM8ZZZZZ
* 777M::::::Z7777777Z77 N++ZZZZNN
* 7777M:::::M7777777$777M $++IZZZZM
* M777$:::::N777777*M7777M +++++ZZZDN
* NN$::::::7777$*M777777N N+++ZZZZNZ
* N::::::N:7*O:77777777 N++++ZZZZN
* M::::::::::::N77777777+ +?+++++ZZZM
* 8::::::::::::D77777777M O+++++ZZ
* ::::::::::::M777777777N O+?D
* M:::::::::::M77777777778 77=
* D=::::::::::N7777777777N 777
* INN===::::::=77777777777N I777N
* ?777N========N7777777777787M N7777
* 77777*D======N77777777777N777N? N777777
* I77777$$*N7===M$$77777777$77777777*MMZ77777777N
* $$$$$$$$$$*NIZN$$$$$$$$*M$$7777777777777777ON
* M$$$$$$$*M M$$$$$$$*N=N$$$$7777777$$*ND
* O77Z$$$$$$$ M$$$$$$$*MNI==*DNNNNM=~N
* 7 :N MNN$$$*M$ $$$777$8 8D8I
* NMM.:7O 777777778
* 7777777MN
* M NO .7:
* M : M
* 8
*/
// Constant matcher factory methods
ALL_STEP(0, "全部") {
@Override
public List<String> getUmList(List<String> umUsers,
List<String> faqPrevRecorderUmUsers) {
return ListUtils.unionAndDistinct(umUsers, faqPrevRecorderUmUsers);
}
},
PEND_AUDIT_STEP(1, "待通过审核") {
@Override
public List<String> getUmList(List<String> umUsers,
List<String> faqPrevRecorderUmUsers) {
return faqPrevRecorderUmUsers;
}
},
AUDITING_STEP(2, "审核中") {
@Override
public List<String> getUmList(List<String> umUsers,
List<String> faqPrevRecorderUmUsers) {
return faqPrevRecorderUmUsers;
}
},
PASS_AUDIT_STEP(3, "已通过审核") {
@Override
public List<String> getUmList(List<String> umUsers,
List<String> faqPrevRecorderUmUsers) {
return umUsers;
}
};
/**
* {@code STEP_MAP} include all step enum and isn`t change.
*/
@Native private static final Map<Integer, StepEnum> STEP_MAP = ImmutableMap.of(
ALL_STEP.getCode(), ALL_STEP,
PEND_AUDIT_STEP.getCode(), PEND_AUDIT_STEP,
AUDITING_STEP.getCode(), AUDITING_STEP,
PASS_AUDIT_STEP.getCode(), PASS_AUDIT_STEP
);
private Integer code;
private String value;
/**
* Return um information list
*
* @param umUsers
* @param faqPrevRecorderUmUsers
* @return
*/
public abstract List<String> getUmList(List<String> umUsers,
List<String> faqPrevRecorderUmUsers);
StepEnum(Integer code,
String value) {
this.code = code;
this.value = value;
}
public Integer getCode() {
return code;
}
public String getValue() {
return value;
}
/**
* Return um information list by {@param step} , and the {@param step} must in {@link FaqStepEnum}.
*
* @param umUsers
* @param faqPrevRecorderUmUsers
* @param step
* @return
*/
public static List<String> getUmListByStep(List<String> umUsers,
List<String> faqPrevRecorderUmUsers,
Integer step) {
if (Objects.isNull(step)) {
LoggerUtil.warn("step is null.");
return Collections.emptyList();
}
return STEP_MAP.get(step).getUmList(umUsers, faqPrevRecorderUmUsers);
}
public static void main(String[] args) {
List<String> a = Arrays.asList("a");
List<String> b = Arrays.asList("b");
Integer step = 1;
System.out.println(StepEnum.AUDITING_STEP.getUmList(a, b));
System.out.println(StepEnum.ALL_STEP.getUmList(a, b));
System.out.println(StepEnum.PEND_AUDIT_STEP.getUmList(a, b));
System.out.println(StepEnum.PASS_AUDIT_STEP.getUmList(a, b));
System.out.println(StepEnum.getUmListByStep(a, b, step));
}
}
四、输出结果
[b]
[a, b]
[b]
[a]
[b]
关注我的技术公众号《漫谈人工智能》,每天推送优质文章