策略模式代码示例(二)

一、定义

策略模式,针对每一个不同的类型,调用具有共同接口的不同实现类,从而使得它们可以相互替换。

策略模式 ,针对实现同一接口的不同的类,采用不同的策略。比如,面对高级会员、初级会员会采用不同的折扣。

策略模式,可以避免大量的if和else。

二、角色

策略模式涉及到三个角色:

●  环境(Context)角色:调用策略

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

●  具体策略(ConcreteStrategy)角色:实现抽象策略接口,包装了相关的算法或行为。

三、代码示例

type 枚举

复制代码
public enum TypeEnum {

    /**
     * 类型一
     */
    FIRST_TYPE(1, "类型一"),

    /**
     * 类型二
     */
    SECOND_TYPE(2, "类型二"),

    /**
     * 类型三
     */
    THIRD_TYPE(3, "类型三"),
    ;

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

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


    public Integer getType() {
        return type;
    }

    public String getTypeName() {
        return typeName;
    }


    /**
     * 根据 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;
    }

}

基础类:

复制代码
/**
 * 基础类,写不同策略的公共的代码,避免代码重复
 */
@Service
public class TypeStrategyBaseService {

    /**
     * 公共代码,避免重复
     */
    public void doCommon() {
        System.out.println("execute common method.");
    }
}

策略模式接口:

复制代码
/**
 * 策略模式接口
 *
 */
public interface TypeStrategy {

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

    /**
     * 获取类型
     * @return
     */
    Integer getType();
}

第一种策略:

复制代码
/**
 * 第一种策略
 */
@Service
public class FirstTypeStrategyServerImpl extends TypeStrategyBaseService implements TypeStrategy {

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

    @Override
    public Integer getType() {
        return TypeEnum.FIRST_TYPE.getType();
    }

}

第二种策略:

复制代码
/**
 * 第二种策略
 */
@Service
public class SecondTypeStrategyServiceImpl extends TypeStrategyBaseService implements TypeStrategy {

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

    @Override
    public Integer getType() {
        return TypeEnum.SECOND_TYPE.getType();
    }

}

配置 策略对应的 map:

复制代码
@Component
public class SpringApplicationContextHolder implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        applicationContext = ctx;
    }

    /**
     * 获取类型为 key,策略作为value 的 map
     *
     */
    public static <T> Map<String, T> getBeansOfType(Class<T> classType) {
        if (applicationContext == null) {
            log.warn("ApplicationContext is null.classType:{}", JSON.toJSONString(classType));
            throw new IllegalStateException("getBeansOfType failed.ApplicationContext is null");
        }
        return applicationContext.getBeansOfType(classType);
    }


}

策略 Context

复制代码
/**
 * 策略 Context,获取策略
 */
@Component
public class TypeStrategyContext {
    /**
     *  存在多个容器的时候会被加载多次
     */
    private static volatile Map<Integer, TypeStrategy> strategyMap;

    @PostConstruct
    public static void init() {
        if (strategyMap == null) {
            Map<String, TypeStrategy> subBeanMap = SpringApplicationContextHolder.getBeansOfType(TypeStrategy.class);
            strategyMap = subBeanMap.values().stream().collect(Collectors.toMap(TypeStrategy::getType, typeStrategy -> typeStrategy));
        }
    }

    /**
     * 根据 type 获取不同的策略,再执行业务逻辑。
     */
    public static TypeStrategy getStrategyByType(int type) {
        return strategyMap.get(type);
    }

}

调用策略的类:

复制代码
/**
 * 调用类
 *
 */
@Service
public class TypeStrategyClientService {


    /**
     * 根据 type 获取不同的策略,再执行业务逻辑。
     */
    public String doSthByType(Integer type, String param) {
        TypeStrategy typeStrategy = TypeStrategyContext.getStrategyByType(type);
        if (typeStrategy == null) {
            throw new IllegalStateException("类型"+ type + "不存在策略");
        }
        return typeStrategy.doSth(param);
    }


}

测试:

复制代码
@Test
public void testDoSthByType2()  {
    String result = typeStrategyClientService.doSthByType(1, "12345");
    System.out.println("==============> typeStrategyClientService result: " + result);
}

输出结果:

type 为1时,结果为:

复制代码
execute common method.
==============> result: FirstStrategy doSth 12345

type为2时,结果为:

复制代码
execute common method.
==============> result: SecondStrategy doSth 12345
相关推荐
西岭千秋雪_16 分钟前
Kafka客户端整合
java·spring boot·分布式·kafka·linq
leonardee20 分钟前
Golang笔记——Interface类型
java·后端
我是好小孩27 分钟前
【Android】RecyclerView的高度问题、VH复用概念、多子项的实现;
android·java·网络
张彦峰ZYF29 分钟前
高并发优惠权益聚合接口的优雅实现(含超时控制 + 来源标识 + Fallback 降级)
java·后端·面试
4Forsee31 分钟前
【Android】模板化解决复杂场景的滑动冲突问题
android·java·rpc
若水不如远方35 分钟前
深入 Dubbo 服务暴露机制:从注解到网络的完整链路剖析
java·dubbo
tanxinji37 分钟前
Netty编写Echo服务器
java·netty
LBuffer1 小时前
破解入门学习笔记题四十七
java·笔记·学习
可可苏饼干1 小时前
TOMCAT
java·运维·学习·tomcat