JAVA设计模式-策略模式及在Springboot2.X中写法

JAVA设计模式-策略模式及在Springboot2.X中写法

策略模式的定义 :策略模式是一种行为型设计模式,定义了一系列算法,并将每个算法封装起来,使它们可以互相替换
策略模式 :在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。

如何解决:将这些算法封装成一个一个的类,任意地替换。

关键代码:实现同一个接口。

应用实例: 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 3、JAVA AWT 中的 LayoutManager。

策略模式三种角色

  • 1、环境上下文(Context)角色:持有一个Strategy引用,委托策略变量调用具体策略所实现的策略接口中的方法。
  • 2、策略(Strategy)角色:抽象角色,通常由一个接口或抽象类实现,此角色给出所有的具体策略类所需接口。
  • 3、具体策略(ConcreteStrategy)角色:具体实现策略接口的类,包装了相关的算法或行为。

一、经典的策略模式写法

java 复制代码
/**
 * 策略接口
 */
public interface Strategy {
    int doOperation(int num1, int num2);
}


/**
 * 加法策略
 */
class OperationAdd implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

/**
 * 减法策略
 */
class OperationSub implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}


/**
 * 策略上下文类
 */
class Context {

    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public Strategy getStrategy() {
        return strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int num1, int num2) {
        return strategy.doOperation(num1, num2);
    }
}


class Main{
    public static void main(String[] args){
        // 策略上下文
        Context context = new Context(new OperationAdd());
        // 加法策略
        System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
        // 减法策略
        context = new Context(new OperationSub());
        System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

    }
}

但是上述的写法中,在具体使用过程中,要需要new具体的策略,而不能简单的传输一些字段来实现

二、Springboot2.X中策略模式写法

参考链接

在springboot中实现的时候可以采用@Component来标记为bean,通过获取bean来直接得到想要的具体策略

下述例子采用数据库存储的方式,将具体的code和beanId关联在一起,通过code-->获取beanId-->获取bean-->执行bean,从而不需要在Context中写if-else,或者在调用过程中写死new具体的策略

同理,使用 读取缓存、读取枚举、读取数据库等方式来实现,一定程度上解耦了抽象类和实体类之间的关联。

1.首先定义策略模式的策略接口

java 复制代码
public interface Strategy {
	int doOperation(int num1, int num2);
}

2.定义具体的策略

在springboot中可以使用@Component标记一个类为组件

实现加法策略

java 复制代码
@Component
public class OperationAdd implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

实现减法策略

java 复制代码
@Component
class OperationSub implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}

3.实现环境上下文Context

java 复制代码
@Component
public class ContextStrategy {

    @Resource
    private OperatorMapper operatorMapper;

    public int executeStrategy(int code,int num1, int num2) {
    	OperatorEntity entity = OperatorMapper.getOperator(code);
    	Strategy strategy = SpringUtils.getBean(entity.getStrategyBeanId(),Strategy.class);
        return strategy.doOperation(num1, num2);
    }
}

4.使用

java 复制代码
@RestController
public class OperatorController {
    @Autowired
    private ContextStrategy contextStrategy;

    @GetMapping("/toDoOperator")
    public String toDoOperator(String code,int num1,int num2){
        return contextStrategy.doOperation(code,num1,num2);
    }
}

5.细节部分

注意:这里有个细节问题,数据库存储的beanId一定要跟我们定义的bean保持一致,否则根据beanId去spring容器中获取实例对象会失败!

附根据beanId获取对应实例对象的utils

java 复制代码
/**
 * 根据beanId 从spring容器中获取对象
 */
@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

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

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }

    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz){
        return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name,Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }

}
相关推荐
夏天的味道٥3 小时前
使用 Java 执行 SQL 语句和存储过程
java·开发语言·sql
冰糖码奇朵5 小时前
大数据表高效导入导出解决方案,mysql数据库LOAD DATA命令和INTO OUTFILE命令详解
java·数据库·sql·mysql
好教员好5 小时前
【Spring】整合【SpringMVC】
java·spring
浪九天6 小时前
Java直通车系列13【Spring MVC】(Spring MVC常用注解)
java·后端·spring
堕落年代6 小时前
Maven匹配机制和仓库库设置
java·maven
功德+n7 小时前
Maven 使用指南:基础 + 进阶 + 高级用法
java·开发语言·maven
香精煎鱼香翅捞饭7 小时前
java通用自研接口限流组件
java·开发语言
ChinaRainbowSea7 小时前
Linux: Centos7 Cannot find a valid baseurl for repo: base/7/x86_64 解决方案
java·linux·运维·服务器·docker·架构
囧囧 O_o7 小时前
Java 实现 Oracle 的 MONTHS_BETWEEN 函数
java·oracle
去看日出8 小时前
RabbitMQ消息队列中间件安装部署教程(Windows)-2025最新版详细图文教程(附所需安装包)
java·windows·中间件·消息队列·rabbitmq