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);
    }

}
相关推荐
装不满的克莱因瓶10 分钟前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
n北斗17 分钟前
常用类晨考day15
java
骇客野人21 分钟前
【JAVA】JAVA接口公共返回体ResponseData封装
java·开发语言
yuanbenshidiaos1 小时前
c++---------数据类型
java·jvm·c++
向宇it1 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
Lojarro2 小时前
【Spring】Spring框架之-AOP
java·mysql·spring
莫名其妙小饼干2 小时前
网上球鞋竞拍系统|Java|SSM|VUE| 前后端分离
java·开发语言·maven·mssql
isolusion2 小时前
Springboot的创建方式
java·spring boot·后端
zjw_rp2 小时前
Spring-AOP
java·后端·spring·spring-aop
Oneforlove_twoforjob3 小时前
【Java基础面试题033】Java泛型的作用是什么?
java·开发语言