一、策略模式简介
- 说白了就是用一个接口统一管理一系列类似算法,把算法变成实现独立到一个个实现该接口的类中,然后就可以通过多态,来实现对不同算法的调用。
- 策略模式可以避免使用大量的 if-else 或 switch-case 语句,使代码更加清晰、简洁。
- 策略模式的缺点是,由于每个算法都是一个独立的类,因此可能会导致类的数量增多。
二、框架定义
- 首选需要定义两个接口,一个抽象类:分别是“可选性接口”,“选择器接口”,“抽象选择器”
- 可选性接口:Selectable
该接口用于标记一个策略类表示该策略类可以注册到选择器,返回策略的标识
public interface Selectable {
String getServiceName();
}
- 选择器接口:Selector
可以通过策略标识获取到对应的策略类
public interface Selector < T extends Selectable> {
T getService(String serviceName);
}
- 抽象选择器:ServiceSelector
利用springboot IOC 自动注册指定策略接口的实现类,并可以根据策略标识获取到对应的策略类
public abstract class ServiceSelector<T extends Selectable> implements Selector<T> {
private Map<String, T> servicesMap;
@Autowired(required = false)
private void setServices(List<T> services) {
servicesMap = services.stream().collect(Collectors.toMap(T::getServiceName, Function.identity(), (k1, k2) -> k2));
}
public T getService(String name) {
return servicesMap.get(name);
}
三、使用框架
- 首先定义一个策略接口,继承或实现Selectable即可
public interface IUniqueNameSelectable extends Selectable, IUniqueName {
}
- 定义策略接口的实现类
@Service
public class UserUniqueNameService implements IUniqueNameSelectable {
@Autowired
UserPwdMapper userPwdMapper;
@Override
public String getServiceName() {
return "User";
}
@Override
public boolean isNameUnique(UniqueNameDto dto) {
return userPwdMapper.countByName(dto.getName()) == 0;
}
}
@Service
public class KeywordUniqueNameService implements IUniqueNameSelectable {
@Autowired
KnowledgeTypeMapper knowledgeTypeMapper;
@Override
public String getServiceName() {
return "Keyword";
}
@Override
public boolean isNameUnique(UniqueNameDto dto) {
return knowledgeTypeMapper.countByName(dto.getName()) == 0;
}
}
- 定义具体策略接口选择器,只需要继承抽象选择器ServiceSelector
指定具体的策略接口,选择器自动将具体策略接口的实现类注册进来
@Component
public class UniqueNameSelector extends ServiceSelector<IUniqueNameSelectable> {
}
- 使用选择器:将选择器注入到对应服务中,通过getService获取到对应的策略接口的实现类
@Service
public class UniqueNameQueryService implements IUniqueNameQueryService {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(UniqueNameQueryService.class);
@Autowired
ServiceSelector<IUniqueNameSelectable> uniqueNameSelector;
@Override
public boolean isUniqueName(UniqueNameDto dto) {
IUniqueName uniqueName = uniqueNameSelector.getService(dto.getTradeName());
if (null != uniqueName){
return uniqueName.isNameUnique(dto);
}
return false;
}