【设计模式】实战!工作中策略工厂模式如何应用?

179 阅读3分钟

背景

日常需求开发过程中,常对于不同的条件下要选择不同的策略,通过 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: 使用该方式的缺点是什么?

  • 如文中的示例,每增加一种类型的具体策略类,都需要实现其对应的算法。