策略模式在应用中的实践

Posted by Coderidea on June 2, 2020

行为模式有一种模式叫策略模式(Strategy Pattern),一个类的行为或其算法可以在运行时更改。在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。

如何解决:将这些算法封装成一个一个的类,任意地替换。关键代码:实现同一个接口。 

优点:

1、算法可以自由切换。

2、避免使用多重条件判断。

3、扩展性良好。

缺点:

1、策略类会增多。

2、所有策略类都需要对外暴露。

使用场景: 

1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。2、一个系统需要动态地在几种算法中选择一种。3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

应用案例:

实现按任务类型执行类型相对应的任务,不同的任务对应的是不同的算法。

1. 定义一个接口或抽象类

package com.tiny.strategy;
/**

* BaseTask
*
* @author tianya
* @date 2020/11/29
*/
public abstract class BaseTask {
abstract void run();
}

 

2. 定义几组实现的类

package com.tiny.strategy;
/**
 * WeekTask
 *
 * @author tianya
 * @date 2020/11/29
 */
public class WeekTask extends BaseTask {
    @Override
    void run() {
        System.out.println("run weekTask");
    }
}


package com.tiny.strategy;
/**
 * DayTask
 *
 * @author tianya
 * @date 2020/11/29
 */
public class DayTask extends BaseTask {
    @Override
    void run() {
        System.out.println("run dayTask");
    }
}

 

3. 定义一个工厂,根据类型去实现对应的任务。

package com.tiny.strategy;
/**
 * TaskFactory
 *
 * @author tianya
 * @date 2020/11/29
 */
public interface TaskFactory {
    /**
     * 获取Task
     *
     * @param type
     * @return
     */
    BaseTask getTask(String type);
}


package com.tiny.strategy;
import java.util.HashMap;
import java.util.Map;
/**
 * TaskFactoryImpl
 *
 * @author tianya
 * @date 2020/11/29
 */
public class TaskFactoryImpl implements TaskFactory {
    private static final Map<String, BaseTask> taskMap = new HashMap(2);
    public BaseTask getTask(String type) {
        if ("day".equals(type)) {
            return new DayTask();
        }
        if ("week".equals(type)) {
            return new WeekTask();
        }

        throw new IllegalArgumentException("task type not found");
    }
}

这里为了简单工厂方法直接用的if,这里可以定义一个map去替代 if。

4.调用入口。

package com.tiny.strategy;
/**
 * App
 *
 * @author tianya
 * @date 2020/11/29
 */
public class App {
    public static void main(String[] args) {
        TaskFactory taskFactory = new TaskFactoryImpl();
        BaseTask task = taskFactory.getTask("day");
        task.run();
        task = taskFactory.getTask("week");
        task.run();
    }
}

 

代码的github 地址:

https://github.com/tianyaxiang/ApplicationArchitecture/tree/master/strategy

案例中生成策略类我们用了工厂模式,这样把变化点集中到了工厂方法里,有新增的任务修改工厂类就好了。这里有个优化的点,可以利用Spring 实现一个动态的工厂,如果有需求的话。