首页 > 其他分享 >策略模式代码示例(二)

策略模式代码示例(二)

时间:2024-03-01 16:05:20浏览次数:20  
标签:return 策略 示例 代码 模式 param type public String

一、定义

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

标签:return,策略,示例,代码,模式,param,type,public,String
From: https://www.cnblogs.com/expiator/p/18047262

相关文章

  • 从代码行者到团队领航者:软件团队管理的深度知识与能力探索
    从代码行者到团队领航者:软件团队管理的深度知识与能力探索随着技术的不断进步和市场的快速变化,软件团队管理者的角色已经超越了单纯的技术领导,成为了企业战略执行和团队文化塑造的核心。这要求团队管理者不仅具备深厚的技术功底,还需要在多个领域展现出卓越的能力。一、技术深度......
  • 观察者模式
    察者模式是一种设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当这个主题对象的状态发生变化时,会通知所有的观察者对象,使它们能够自动更新自己。在Java中,观察者模式可以使用java.util包中的Observer和Observable来实现。具体步骤如下:定义主题对......
  • 代码随想录算法训练营第三十二天 | 45.跳跃游戏II ,55. 跳跃游戏,122.买卖股票的最佳时
     122.买卖股票的最佳时机II 已解答中等 相关标签相关企业 给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购......
  • Ubuntu编译安卓代码时tmp目录空间不足
    使用ubuntu编译安卓代码时,有些临时文件或目录是会被放到/tmp目录下的,如果自己环境的/tmp空间不够大,则会产生如下的编译错误: 查看自己/tmp目录使用情况,发现确实空间所剩不多: 解决方法一:修改TMPDIR系统环境变量。命令:export TMPDIR=新的绝......
  • 外观模式(facade pattern)
    外观模式(facadepattern) 外观模式(FacadePattern),也叫门面模式,外观模式的原始定义是:为子系统中的一组接口提供统一的接口。它定义了一个更高级别的接口,使子系统更易于使用。外观模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模......
  • 代理模式2 (设计模式)
    ClassLoader的作用在java运行的时候,ClassLoader(类加载器)负责将类文件加载到内存中,并转化为java运行时的java类。ClassLoader是java虚拟的(JVM)的一部分,它的主要作用是动态的加载java类。 1.当java程序需要某个类时,ClassLoader负责将该类的字节码(.class)文件加载到内......
  • Go语言精进之路读书笔记第41条——有层次地组织测试代码
    聚焦位于测试包内的测试代码该如何组织41.1经典模式—平铺测试函数各自独立,测试函数之间没有层级关系,所有测试平铺在顶层41.2Unit家族模式测试套件(TestSuite)和测试用例(TestCase)41.3测试固件测试固件是一个人造的、确定性的缓解,在这个环境中进行测试,测试结果是可重复的......
  • 使用ConfuserEx代码混淆工具保护你的.NET应用程序
    .NET反编译相关的文章4款免费且实用的.NET反编译工具.NET反编译神器ILSpy怎么用?ConfuserEx.NET混淆工具安装GitHub开源地址:https://github.com/mkaring/ConfuserEx下载地址:https://github.com/mkaring/ConfuserEx/releases ConfuserEx-GUI.zip包解压即可使用:使......
  • git拉取多个仓库代码配置多个密钥
    当你需要使用多个仓库地址并且使用不同的ssh密钥时就会遇到配置问题。先看配置文件~/.ssh/configHostgithub.com-just-beginerHostNamegithub.comUseryiconIdentityFile~/.ssh/github_rsaHostgitee.com-justshuangHostNamegitee.com......
  • 写给rust初学者的教程(一):枚举、特征、实现、模式匹配
    这系列RUST教程一共三篇。这是第一篇,介绍RUST语言的入门概念,主要有enum\trait\impl\match等语言层面的东西。安装好你的rust开发环境,用cargo创建一个空项目,咱们直接上代码。懵逼的同僚可以参考我8年前的rust文章:https://www.iteye.com/blog/somefuture-2275494,虽然8年了,然并不......