设计模式之策略模式

3,487 阅读5分钟

前言

一个月更新一片博客哈,又来坚持了~(这是第三个月啦) 最近碰巧在做策略模式的重构,刚好为写博客提供了素材,接下来为大家介绍策略模式~

策略模式的定义

策略模式:属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。

其实就是对算法(也就是我们的业务逻辑的处理)的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。

了解完定义后,我们再来看下策略模式通用类图:

根据这个图我们看到策略模式参与者:

Context:上下文角色,持有一个Strategy的引用。

Strategy:抽象策略角色,这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口

ConcreteStrategy:具体策略角色,包装了相关的算法或行为,实现或继承了抽象策略角色。

这三个角色的功能职责都十分明确,对应的源码实现也十分简单,现在我们就来快速看下每个角色对应的通用源码。

有了策略模式的基本代码结构,在客户端类中使用十分简单,想要哪个策略,就产生出它的具体策略对象放入上下文对象内,然后由上下文对象执行具体策略操作即可,具体代码如下:

这就是策略模式的简单实现。

策略模式使用场景以及实例

我们经常会遇到很多的 if/else 代码块

比如有一个职场惩罚的需求,迟到罚款100元,工作睡觉罚款200元。我们现在的惩罚只有两个,当有越来越多的 惩罚手段,那我们这里的判断条件就会越来越多。造成代码块的冗余。

public class WorkPunish {

   public static void main(String[] agrs){
       String state ="late";
       punish(state);
   }
   
   public static void punish(String state){
       if ("late".equals(state)){
           System.out.println("罚100");
       }else if ("sleep".equals(state)){
           System.out.println("罚200");
       }  System.out.println("警告");
   }
}

这个时候策略模式就应运而生。使用策略模式可以帮助我们将每个处理逻辑封装成独立的类,客户端类需要进行哪种处理逻辑就使用对应的类,调用其封装了业务处理细节的方法即可。

接下来就是使用策略模式的demo了。

首次定义一个抽象接口,包含惩罚方法

public interface IPunish {
    void exePunish();
}

接下来就是写具体的实现类,实现该抽象接口,实现类实现了抽象类的方法,将具体的逻辑在这里处理。 注意,我们在这立还继承了InitializingBean,InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法。会将对象注册,接下来看注册的实现~

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class LatePunish implements IPunish,InitializingBean{
    public void exePunish() {
        System.out.println("罚100");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        PunishFactory.registerPunish("late", this);
    }
}

这是一个工厂类。将所有的实现累在初始化的时候都注册到这里,存放在map中。根据客户端的需要选取对应的实现对象,来调用具体的方法。

import java.util.HashMap;
import java.util.Map;
public class PunishFactory {

    private static Map<String,IPunish> punishMap = new HashMap<String,IPunish>();
    private PunishFactory() {}
    private static final IPunish EMPTY = new EmptyPunish();
    //获取
    public static IPunish getPunish(String state) {
        IPunish result = punishMap.get(state);
        return result == null ? EMPTY : result;
    }
    //将处罚对象注册到这里
    public static void registerPunish(String state,IPunish o){
        punishMap.put(state, o);
    }
    private static class EmptyPunish implements IPunish {
        public void exePunish() {
            // Empty class
        }
    }
}

接下里就是重构之后那一堆if/else的处理逻辑,只需要根据对应的状态,取到赌赢的对象,调用实现方法,完成需求

public class WorkPunish {
    public static void main(String[] agrs){
        String state ="late";
        IPunish punish = PunishFactory.getPunish(state);
        punish.exePunish();
    }
}

到这里我们的实现就结束了,这就是使用策略模式的一种场景。

策略模式的优点

使用策略模式,可以在不修改原有系统的基础上更换算法或行为,可以灵活地增加新的算法或行为,提供了系统的扩展性

策略模式提供了对一类算法进行管理维护。

使用策略模式可以避免使用多重条件判断,由外部模块决定所要执行的策略类。

策略模式的缺点

客户端必须知道所有的策略类,并自行决定使用哪一个策略类。

会产生很多策略类,使得类的项目增多。

结语

到这里,本文对策略模式的学习就此结束,当然关于策略模式的内容远不止这些,文章中举例是结合了策略模式和工厂模式,重构了代码。那么对于工厂模式大家是否理解,下期文章再见哈~