策略模式的代码实践示例

一、定义

策略模式,针对每一个不同的类型,调用具有共同接口的不同实现类,从而使得它们可以相互替换。
策略模式 ,针对实现同一接口的不同的类,采用不同的策略。比如,面对高级会员、初级会员会采用不同的折扣。
策略模式,可以避免大量的if和else。

二、角色

策略模式涉及到三个角色:
●  环境(Context)角色:调用策略
●  抽象策略(Strategy)角色:抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
●  具体策略(ConcreteStrategy)角色:实现抽象策略接口,包装了相关的算法或行为。

三、示例

  • 策略模式接口 Strategy:
/**
 * 策略模式接口
 *
 */
public interface Strategy {

    /**
     * 做某事
     * @param param
     * @return
     */
    String doSth(String param) ;

}
  • 公共类:
/**
 * 基础类,写不同策略的公共的代码,继承基础类,写公共逻辑,避免代码重复
 */
@Service
public class StrategyBaseService {

    /**
     * 公共代码,避免代码重复
     */
    public void doCommon() {
        System.out.println("do sth common.");
    }
}
  • 第一种策略 FirstStrategyServerImpl:

继承基础类,实现 Strategy接口。

@Component 注解的名称为 TypeNameConstant 常量,见后续代码。

/**
 * 第一种策略
 */
@Component(TypeNameConstant.TYPE_FIRST)
public class FirstStrategyServerImpl extends StrategyBaseService implements Strategy  {

    /**
     * 业务逻辑
     */
    @Override
    public String doSth(String param) {
        doCommon();
        return "FirstStrategy doSth " + param;
    }

}

  • 第二种策略 SecondStrategyServiceImpl:
/**
 * 第二种策略
 */
@Component(TypeNameConstant.TYPE_SECOND)
public class SecondStrategyServiceImpl extends StrategyBaseService implements Strategy {

    /**
     * 业务逻辑
     */
    @Override
    public String doSth(String param) {
        doCommon();
        return "SecondStrategy doSth " + param;
    }

}

  • 不同策略的 @Component名称:
/**
 *  不同策略的 @Component名称
 */
public class TypeNameConstant {

    private TypeNameConstant() {}

    /**
     * 比如 FirstStrategy 的 @Component名称是 TypeConstant.TYPE_FIRST (这个常量对应字符串 first)
     */
    public static final String TYPE_FIRST = "first";
    public static final String TYPE_SECOND = "second";
    public static final String TYPE_THIRD = "third";

}
  • 类型枚举:
/**
 *  type枚举. @Getter 要是用不了,可以直接写 属性对应的 get()方法。
 */
@Getter
public enum TypeEnum {

    /**
     * 类型一
     */
    FIRST_TYPE(1, TypeNameConstant.TYPE_FIRST),

    /**
     * 类型二
     */
    SECOND_TYPE(2, TypeNameConstant.TYPE_SECOND),

    /**
     * 类型三
     */
    THIRD_TYPE(3, TypeNameConstant.TYPE_THIRD),

    ;

    /**
     * 类型
     */
    private final Integer type;
    private final String typeName;

    TypeEnum(Integer type, String text) {
        this.type = type;
        this.typeName = text;
    }

    /**
     * 根据 type 获取枚举
     * @param type
     * @return
     */
    public static TypeEnum getByType(Integer type) {
        for (TypeEnum typeEnum : TypeEnum.values()) {
            if (typeEnum.getType().equals(type)) {
                return typeEnum;
            }
        }
        return null;
    }

    public static TypeEnum getByName(String name) {
        for (TypeEnum typeEnum : TypeEnum.values()) {
            if (typeEnum.getTypeName().equals(name)) {
                return typeEnum;
            }
        }
        return null;
    }

}

  • StrategyContext 调用策略:

策略模式,会有一个 Context 类,调用策略。

/**
 * 策略 Context,获取策略
 */
@Service
public class StrategyClientService {

    @Resource
    private StrategyContext strategyContext;

    /**
     * 根据 type 获取不同的策略,再执行业务逻辑。
     */
    public String doSthByType(Integer type, String param) {
        Strategy strategy = strategyContext.getStrategyByType(type);
        return strategy.doSth(param);
    }


}
  • 根据类型,使用策略:
/**
 * 调用类
 *
 */
@Service
public class StrategyClientService {


    @Resource
    private StrategyContext strategyContext;

    /**
     * 根据 type 获取不同的策略,再执行业务逻辑。
     */
    public String doSthByType(Integer type, String param) {
        Strategy strategy = strategyContext.getStrategyByType(type);
        return strategy.doSth(param);
    }


}

测试代码

没有单元测试类,也可以直接写个 Controller 测试。

    public void testDoSthByType()  {
        String result = strategyClientService.doSthByType(1, "12345");
        System.out.println("==============> result: " + result);
    }

输出结果:

type 为1时,结果为:

execute common method.
==============> result: FirstStrategy doSth 12345

type为2时,结果为:

execute common method.
==============> result: SecondStrategy doSth 12345

参考资料:

《java与模式》

posted on 2024-02-09 17:35  乐之者v  阅读(20)  评论(0编辑  收藏  举报

导航