首页 > 其他分享 >策略模式【结合springboot实现】

策略模式【结合springboot实现】

时间:2024-01-23 20:31:49浏览次数:28  
标签:springboot Component 模式 import 维度 org public 策略

Hello!~大家好啊,很高兴我们又见面了,今天我们一起学习设计模式–【策略模式】

初次对此模式不懂的,或者想偷懒的,我强烈建议大家跟着我的一起把概念和代码一起敲一遍!~为啥子??因为我就是这样学会的,哈哈哈!

1.首先我们看下此模式的整体UML

selector:选择器又叫做上下文context,【作用】通过不同的标识从而获取对应的策略实例(这是很关键的一个点,你细品~)

抽象策略: 如图所示,这是策略模式的顶层接口【就相当于领导~干运筹帷幄的】

策略实例 n:封装不同算法业务的实例对象,【就是特么真正干活的~!比如俺们码农】

image.png

2.案例实现

我们一个实际的案例进行实操,掌握这看起来高大上的策略模式,也是后面若你要面试,也能吹牛逼啊~

案例:

比如我们要统计餐厅的人流量数据做统计,统计的时间维度:一周和一个月,我们用策略模式咋实现呢? 我们往下看

实现需求分析:

image.pngimage-20240123192104862

  1. 前置设计:
    1. 我们定义常量标识策略的类型,
    2. 使用者调用时可通过常量获取对应的策略实例
  2. 策略设计
    1. 策略实例: 创建两个Bean实例: 周维度 &&月维度,并实现其中对应的算法和业务
    2. 抽象策略:通常我们定义一个通用的接口或者抽象方法,为啥???为了让外部能够访问啊!否则不是闭关锁国了嘛!~~
  3. 选择器设计: 这块就是挺重要的啦,我们通常采用MAP来存储数据,这样调用者就可以通过策略标识获取对应的策略实例

注意:

对于第三点可以是一道面试题:请问你怎么将策略的Bean注入到MAP中的?(不看答案,别心里好家伙,思考思考~哈哈)

也许你的第一反应:

我就直接将Bean对应的Class写死在``MAP中,然后通过applicationContext.getBaen()`获取其实例,这是最简单粗暴的!~(也一看就是菜鸡写法~哈哈哈)

若是这样回答,面试官肯定会问,这个通过写死的方法,那么下次我想增加其他维度的那不是要再次往Map中再添加,这麻烦先不说,也不符合开闭原则啊!~

你尴尬的扣了扣脚,微笑回答到:

是的,这是我一开始使用的,当时业务量不大,只考虑上面的两种情况,我就直接使用采取这种直接写死法,

但后面随着业务线的拓展,我也发现此中写法的弊端:

我的改进措施:(在Springboot的环境中)

1.通过解析注解来实现,给每个策略实例打上一个注解,我们业务是以周和月为维度进行常量标识的

2.过程: 在Springboot启动时,通过扩展点扫描抽象策略,获取它的策略实例

3.然后解析注解,放入MAP

这种就不用对原先代码就行逻辑代码改动,既符合开闭原则,又回到了面试官,爽哉!~

说了这么多,那关于代码我们怎么实现呢?–>耐心点,我们一起往下看

代码实现

1.抽象策略

package org.boyunv.strategy_pattern.handler;

/**
 * <p>
 * 描述:  抽象策略    <br>
 * <p>
 * 需求信息: 【需求ID与需求标题】【客户名称】 <br>
 *
 * @author aristo
 * @date 2024/1/23 19:07
 */
public interface TimeDimensionBaseHandlerInterface {
    //此方法是留给不同策略实体实现不同策略的方法实现
    void  statistic();
}

2.【策略实体】

这里我们注册组件直接采用Spring框架的组件@Component进行注册即可

1.周统计维度

package org.boyunv.strategy_pattern.handler;

import org.springframework.stereotype.Component;

/**
 * <p>
 * 描述:  策略实体: 周统计维度$      <br>
 * <p>
 * 需求信息: 【需求ID与需求标题】【客户名称】 <br>
 *
 * @author aristo
 * @date 2024/1/23 19:12
 */
@Component("week")
public class StatisticByWeekHandler implements TimeDimensionBaseHandlerInterface{
    @Override
    public void statistic() {
        //具体实现
        System.out.println("通过周统计维度实现统计数据");
    }
}

2.月统计维度

package org.boyunv.strategy_pattern.handler;

import org.springframework.stereotype.Component;

/**
 * <p>
 * 描述:  策略实体: 月统计维度$      <br>
 * <p>
 * 需求信息: 【需求ID与需求标题】【客户名称】 <br>
 *
 * @author aristo
 * @date 2024/1/23 19:12
 */
@Component("month")
public class StatisticByMonthHandler implements TimeDimensionBaseHandlerInterface{

    @Override
    public void statistic() {
        System.out.println("通过月统计维度实现统计数据");
    }
}

3.选择器【Inevitable!】

看如下的代码,我们会发现他同样是个组件,@Component

@Resource:将我们注册的weekmonth组件注册进入MAP

package org.boyunv.strategy_pattern.selector;

import org.boyunv.strategy_pattern.handler.TimeDimensionBaseHandlerInterface;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Map;

/**
 * 描述:  选择器,核心重点$      <br>
 * 需求信息: 【需求ID与需求标题】【客户名称】 <br>
 * @date 2024/1/23 19:26
 */
@Component
public class StatisticSelector {
    //这就和我们上面的所说的:定义Map,并通过@Resource注解完成我们刚才week和month的组件注入(很关键的一步哦!~)
    @Resource
    private Map<String, TimeDimensionBaseHandlerInterface> selectorMap;

    //下面根据类型选择策略
    public TimeDimensionBaseHandlerInterface select(String type){
        return selectorMap.get(type);
    }
}

4.我们进行测试

package org.boyunv.strategy_pattern.selector;

import org.boyunv.strategy_pattern.handler.TimeDimensionBaseHandlerInterface;
import org.junit.Test;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Map;

/**
 * 描述:  选择器,核心重点$      <br>
 * 需求信息: 【需求ID与需求标题】【客户名称】 <br>
 * @date 2024/1/23 19:26
 */
@Component
public class StatisticSelector {
    //这就和我们上面的所说的:定义Map,并通过@Resource注解完成我们刚才week和month的组件注入(很关键的一步哦!~)
    @Resource
    private Map<String, TimeDimensionBaseHandlerInterface> selectorMap;

    //下面根据类型选择策略
    public TimeDimensionBaseHandlerInterface select(String type){
        return selectorMap.get(type);
    }

    public  void doInvoke(String type){
        TimeDimensionBaseHandlerInterface handler=select(type);
        handler.doStatistic();
    }
    @Test
    public void invoke(){
        this.doInvoke("week");
        this.doInvoke("month");
    }
}

完结:

通过上面的运行步骤,我们最中实现策略模式的周和月的策略实现

这里面的核心点,再次提醒下:

通过Spring获取接口的实现,并解析实现类上的注解的方式,可以在程序启动时动态的将策略注入到一个Map中,作为策略的容器。

使用时传入标识符(就是常量)就可以获取到对应的策略执行了。

标签:springboot,Component,模式,import,维度,org,public,策略
From: https://blog.51cto.com/u_16339630/9385816

相关文章

  • 设计模式之模板方法
    1.定义定义了一个算法的框架,并允许子类重写其中的某些步骤,而不改变算法的结构2.口语化表述模板方法其实在日常生活中已经很常见,所谓模板方法,就是事先约定好一些事情,后续做时再慢慢实现或者修改,比如组装电脑假设现在需要组装一台台式电脑,一开始计划使用3090显卡,后来根据实际......
  • 从 fatal 错误到 sync.Map:Go中 Map 的并发策略
    从fatal错误到sync.Map:Go中Map的并发策略原创 波罗学 码途漫漫 2024-01-2121:00 发表于上海 听全文为什么Go语言在多个goroutine同时访问和修改同一个map时,会报出fatal错误而不是panic?我们该如何应对map的数据竞争问题呢?码途漫漫踏实地写......
  • 如何查找SpringBoot应用中的请求路径(不使用idea)
    背景昨天有个同事向我咨询某个接口的物理表是哪个,由于公司业务较多、这块业务的确不是我负责的,也没有使用idea不能全局搜索(eclipse搜不到jar内的字符串),也就回复了不清楚。除了自己写代码输出servlet的路径和类外,发现了一个我之前没用过的方法:SpringBootActuator,分享给大家。......
  • SpringBoot可视化接口开发工具magic-api
    magic-api简介magic-api是一个基于Java的接口快速开发框架,编写接口将通过magic-api提供的UI界面完成,自动映射为HTTP接口,无需定义Controller、Service、Dao、Mapper、XML、VO等Java对象。在SpringBoot中使用1、添加magic-api相关依赖<!--接口快速开发框架 magic-api--><depen......
  • 数据库缓存策略
    数据库缓存策略以下是数据库与缓存的五种常见策略。1缓存旁路缓存旁路(Cache-Aside)在缓存旁路策略中,数据库缓存位于数据库旁边。当应用程序请求数据时,它会首先检查缓存如果缓存中存在数据(缓存命中),则会直接返回数据如果缓存中没有数据(缓存未命中),则应用程序将查询数据库,然......
  • SpringBoot实现RequestBodyAdvice和ResponseBodyAdvice接口
    SpringBoot提供了一种机制,允许开发者在请求体(RequestBody)和响应体(ResponseBody)被处理之前和之后执行自定义逻辑。这通过RequestBodyAdvice和ResponseBodyAdvice接口实现。RequestBodyAdvice:此类用于在请求体被处理之前执行自定义逻辑。例如,你可以使用它来解析请求体,或者......
  • 策略模式
    if...else...的优雅写法,可以配合委托模式一起使用定义:定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户补充定义:处理大量if...else...代码类型:行为型适用场景:系统有很多类,而他们的区别仅仅在于他们的行为策略不同一个系统需......
  • MySQL密码过期策略
    如果要设置密码永不过期的全局策略,可以这样:(注意这是默认值,配置文件中可以不声明)[mysqld]default_password_lifetime=0禁用密码过期:ALTERUSER'testuser'@'localhost'PASSWORDEXPIRENEVER;......
  • SpringBoot是什么
    SpringBoot帮我们简单、快速地创建一个独立的、生产级别的Spring应用(说明:SpringBoot底层是Spring)大多数SpringBoot应用只需要编写少量配置即可快速整合Spring平台以及第三方技术特性:快速创建独立Spring应用SSM:导包、写配置、启动运行直接嵌入Tomcat、J......
  • 关于springboot 域认证
    最近项目,客户要求实现域认证,然后登录。网上资料自己整理一下,以备后续使用;springboot域认证,我采用的是ldap方式认证。1.引入插件:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-ldap</artifactId......