背景
日常需求开发过程中,常对于不同的条件下要选择不同的策略,通过 if…else… 或者case等条件判断语句来进行选择,来实现需求。那么有没有一种设计模式可以对其进行优化?
解决方式
可以采用策略模式+工厂模式,来对其优化。让代码看起来更加的优化,易维护。
常见的写法
遇到对于不同的条件下要选择不同的策略的场景,可能大部分的写法如下
if(type=="A"){
//按照A类型去做操作A
}else if(type=="B"){
//按照B类型去做操作B
}else if(type=="C"){
//按照B类型去做操作C
}
那我们思考一个问题,如果条件、方法有很多种的情况下要怎么编写?
- 比如类型有A、B、C、D;
- 操作算法有删除、修改、解析、分享等等操作。
难道要在每个使用的地方写这么多的 if...else,来实现吗?那可能不太合适。
我们可以使用策略模式+工厂模式的方式来解决。
策略工厂模式(示例代码)
/**
* 定义一个抽象类,里面定义需要实现算法--抽象策略类
*/
public abstract class AbstractFileHelper {
/**
* 查询文件
*
* @param request
* @return
*/
public abstract void getFiles(getFileRequest request);
/**
* 删除文件
*
* @param request
*/
public abstract void delete(DeleteRequest request);
......其他操作算法
}
/**
* 类型A的文件,实现其对应的抽象方法--具体策略类
*/
@Component
public class AFileHelper extends AbstractFileHelper {
@Override
public List<File> getFiles(GetFileRequest request) {
//类型A文件的获取算法
}
@Override
@Transactional
public void delete(DeleteFileRequest request) {
//类型A文件的删除算法
}
/**
* 注册
*/
@PostConstruct
private void init() {
FileHelperFactory.register("A", this);
}
}
/**
* 类型B的文件,实现其对应的抽象方法--具体策略类
*/
@Component
public class BFileHelper extends AbstractFileHelper {
@Override
public List<File> getFiles(GetFileRequest request) {
//类型B文件的获取算法
}
@Override
public void delete(DeleteFileRequest request) {
//类型B文件的删除算法
}
/**
* 注册
*/
@PostConstruct
private void init() {
FileHelperFactory.register("B", this);
}
}
/**
* 工厂类,负责将实现算法的类注册进来
*/
public class FileHelperFactory {
private static Map<Integer, AbstractFileHelper> FILE_HELPER_REGISTER = new HashMap<>();
public static AbstractFileHelper getFileHelper(Integer type) {
return FILE_HELPER_REGISTER.get(type);
}
// 工厂的注册方法
public static void register(Integer type, AbstractFileHelper fileHelper) {
FILE_HELPER_REGISTER.put(type, fileHelper);
}
}
/**
* 业务调用方式
* 根据传入的type值,选择不同的算法来实现。而不用使用if...else来判断
*/
FileHelperFactory.getFileHelper(type)
.getFiles(request)
FileHelperFactory.getFileHelper(type)
.delete(request)
QA
思考1: 什么应用场景下,我们应该选择策略工厂设计模式?
- 当一个功能有多种实现方式时,我们应该使用策略设计模式,把功能抽象出来,然后用不同的子类各自提供实现类,在真正使用时,根据业务情况来动态替换。
思考2: 使用该方式的好处是什么?
- 让调用者与被调用者之间解耦,这样好处是,当两者发生变化时,相互之间的影响降到最低,这个原则体显了项目的可维护性
- 由于使用了工厂模式,保证了对象唯一
- 算法易维护,易扩展,只需要修改具体策略类中的方法即可,而无需考虑哪里有调用。
思考3: 使用该方式的缺点是什么?
- 如文中的示例,每增加一种类型的具体策略类,都需要实现其对应的算法。