1、策略模式

1.1、概述

策略模式是一种行为设计模式,它允许在运行时选择算法的行为。它将算法封装在独立的策略类中,使得它们可以相互替换,而不影响客户端代码。这种模式通过将算法的选择从客户端代码中分离出来,提供了更大的灵活性和可维护性。

在Java中,策略模式的设计理念可以通过以下步骤实现:

  1. 定义一个策略接口(或抽象类),该接口定义了所有具体策略类都必须实现的方法。
  2. 创建具体的策略类,实现策略接口,并提供具体的算法实现。
  3. 在客户端代码中,创建一个策略对象,并将其传递给需要使用算法的对象。
  4. 客户端对象使用策略对象来执行特定的算法。

在你提供的代码片段中,我无法确定与策略模式相关的代码。如果你有更多的上下文或示例代码,我可以更好地帮助你理解和应用策略模式。

1.2、优缺点

策略模式具有以下优点:

  • 可以代替if-else
  1. 算法的独立性:策略模式将算法封装在独立的策略类中,使得算法可以独立于客户端代码进行修改和扩展。这样可以提高代码的灵活性和可维护性。

  2. 可替换性:由于策略模式将算法封装在不同的策略类中,因此可以在运行时动态地切换和替换算法。这样可以根据不同的需求选择最合适的算法,而无需修改客户端代码。

  3. 单一职责原则:策略模式将不同的算法封装在不同的策略类中,使得每个策略类只负责一个具体的算法。这样符合单一职责原则,提高了代码的可读性和可维护性。

  4. 扩展性:由于策略模式将算法封装在独立的策略类中,因此可以很容易地添加新的策略类来扩展系统的功能。

策略模式也有一些缺点:

  1. 增加了类的数量:使用策略模式会增加系统中的类的数量,因为每个具体的算法都需要一个对应的策略类。这可能会增加代码的复杂性和理解难度。

  2. 客户端必须了解所有的策略类:客户端必须了解所有可用的策略类,并在运行时选择合适的策略。这可能会增加客户端代码的复杂性。

  3. 策略切换的开销:在运行时切换策略可能会带来一定的开销,特别是在需要频繁切换策略的情况下。这可能会影响系统的性能。

综上所述,策略模式在提供灵活性、可维护性和可扩展性方面具有很多优点,但也需要权衡其增加的类数量和策略切换的开销。在设计和使用策略模式时,需要根据具体的需求和情况进行权衡和选择。

2、SpringBean方式实现

  • bean的名字(默认):实现策略类的名字首字母小写

2.1、实现步奏

  • 可以看到,去获取bean是需要用户自己去做的。

2.2、实现

①定义策略接口

package com.cc.eed.strategy;

/**
* <p>基于SpringBean的策略模式</p>
*
* @author CC
* @since 2023/10/13
*/
public interface ISpringBeanStrategy { /**
* 吃饭
*/
String eating(); /**
* 玩
*/
String play();
}

②定义实现类1

package com.cc.eed.strategy.impl;

import com.cc.eed.strategy.ISpringBeanStrategy;
import org.springframework.stereotype.Component; /**
* <p>小美</p>
*
* @author CC
* @since 2023/10/13
*/
@Component
public class MeiSpringBeanImpl implements ISpringBeanStrategy { /**
* 吃饭
*/
@Override
public String eating() {
return "小美,吃饭!";
} /**
* 玩
*/
@Override
public String play() {
return "小美,玩!";
}
}

定义实现类2

package com.cc.eed.strategy.impl;

import com.cc.eed.strategy.ISpringBeanStrategy;
import org.springframework.stereotype.Component; /**
* <p>小明</p>
*
* @author CC
* @since 2023/10/13
*/
@Component
public class MingSpringBeanImpl implements ISpringBeanStrategy { /**
* 吃饭
*/
@Override
public String eating() {
return "小明,吃饭!";
} /**
* 玩
*/
@Override
public String play() {
return "小明,玩!";
}
}

③定义beanName的枚举

  • 用于使用类型int获取对应的beanName
package com.cc.eed.enums;

import lombok.Getter;
import org.springframework.util.Assert; import java.util.Arrays; /**
* <p></p>
*
* @author CC
* @since 2023/10/13
*/
@Getter
public enum PeopleEnum { MING(1, "小明", "mingSpringBeanImpl"),
MEI(2, "小美", "meiSpringBeanImpl")
; public Integer type; public String name; public String beanName; /** <p>根据类型获取beanName<p>
* @param type type
* @return {@link String}
* @since 2023/10/13
* @author CC
**/
public static String getBeanName(Integer type) {
PeopleEnum peopleEnum = Arrays.stream(values())
.filter(p -> p.getType().equals(type))
.findAny().orElse(null);
Assert.notNull(peopleEnum, "暂不支持的策略模式!");
return peopleEnum.getBeanName();
} PeopleEnum(Integer type, String name, String beanName) {
this.type = type;
this.name = name;
this.beanName = beanName;
} public void setType(Integer type) {
this.type = type;
} public void setName(String name) {
this.name = name;
} public void setBeanName(String beanName) {
this.beanName = beanName;
}
}

④使用springBean工具类获取beanName

⑤使用

  • 传入不同的类型,获取不同的策略
@Test
public void test02()throws Exception{
//根据BeanName获取具体的bean,实现策略模式
//根据人员ID(或者类型)获取不同的bean
String beanName = PeopleEnum.getBeanName(1);
ISpringBeanStrategy bean = (ISpringBeanStrategy) SpringBeanUtil.getBean(beanName); String eating = bean.eating();
System.out.println(eating); String play = bean.play();
System.out.println(play);
}
  • 结果:

    传入1



    传入2



    传入除了1/2的

3、简单工厂模式实现(推荐)

  • 加自定义Bean的名字

3.1、实现步奏

  • 可以看到,去获取bean是交给工厂去做的,用户只需要传入类型即可。

3.2、实现

①定义策略接口

package com.cc.eed.strategy;

/**
* <p>简单工厂模式 - 实现的策略模式</p>
*
* @author CC
* @since 2023/10/13
*/
public interface IFactoryStrategy { /**
* 吃饭
*/
String eating(); /**
* 玩
*/
String play();
}

②生产策略bean的工厂

  • 由于使用的@Resource注解,BUSINESS_FACTORY会自动注入所有实现了IFactoryStrategy接口的Bean。@Resource注解是Spring提供的一种依赖注入的方式,它会根据类型进行自动装配。在这个例子中,BUSINESS_FACTORY是一个Map类型的成员变量,它的键是字符串类型,值是IFactoryStrategy类型。当Spring容器启动时,会扫描并找到所有实现了IFactoryStrategy接口的Bean,并将它们自动注入到BUSINESS_FACTORY中。
  • 由于BUSINESS_FACTORY使用了ConcurrentHashMap作为实现,它会根据PirateEnum.values().length的大小来初始化容量。这样可以确保BUSINESS_FACTORY的大小与实际注入的Bean数量一致,提高性能和效率。
package com.cc.eed.strategy;

import com.cc.eed.enums.PirateEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert; import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; /**
* <p>简单工厂</p>
* <li>可以生产多个策略</li>
*
* @author CC
* @since 2023/10/13
*/
@Component
public class StrategyByFactory { /**
* 1、批量注入实现了 IFactoryStrategy 的Bean。
* 2、用bean的数量当做map的大小
*/
@Resource
private final Map<String, IFactoryStrategy> BUSINESS_FACTORY = new ConcurrentHashMap<>(PirateEnum.values().length); //生成的策略...
/** <p>根据类获取不同的Bean<p>
* @param type type
* @return {@link IFactoryStrategy}
* @since 2023/10/13
* @author CC
**/
public IFactoryStrategy getBusinessMap(Integer type){
Assert.notNull(type, "类型不能为空!");
String beanName = PirateEnum.getBeanName(type);
return BUSINESS_FACTORY.get(beanName);
} //生成的其他策略... }

③策略实现类1

package com.cc.eed.strategy.impl;

import com.cc.eed.enums.PirateEnum;
import com.cc.eed.strategy.IFactoryStrategy;
import org.springframework.stereotype.Component; /**
* <p>路飞</p>
*
* @author CC
* @since 2023/10/13
*/
@Component(PirateEnum.LF_BEAN_NAME)
public class LuFeiFactoryStrategy implements IFactoryStrategy {
/**
* 吃饭
*/
@Override
public String eating() {
return "路飞,吃饭!";
} /**
* 玩
*/
@Override
public String play() {
return "路飞,玩!";
}
}

③策略实现类2

package com.cc.eed.strategy.impl;

import com.cc.eed.enums.PirateEnum;
import com.cc.eed.strategy.IFactoryStrategy;
import org.springframework.stereotype.Component; /**
* <p>明哥</p>
*
* @author CC
* @since 2023/10/13
*/
@Component(PirateEnum.MG_BEAN_NAME)
public class MingGgFactoryStrategy implements IFactoryStrategy {
/**
* 吃饭
*/
@Override
public String eating() {
return "明哥,吃饭!";
} /**
* 玩
*/
@Override
public String play() {
return "明哥,玩!";
}
}

④定义beanName的枚举

package com.cc.eed.enums;

import org.springframework.util.Assert;

import java.util.Arrays;

/**
* <p></p>
*
* @author CC
* @since 2023/10/13
*/
public enum PirateEnum { MG(11, "明哥", PirateEnum.MG_BEAN_NAME), LF(22, "路飞", PirateEnum.LF_BEAN_NAME) ; public Integer type; public String name; public String beanName; /**
* 自定义的beanName
*/
public static final String MG_BEAN_NAME = "mingGg_11";
public static final String LF_BEAN_NAME = "luFei_22"; /** <p>根据类型获取beanName<p>
* @param type type
* @return {@link String}
* @since 2023/10/13
* @author CC
**/
public static String getBeanName(Integer type) {
PirateEnum pirateEnum = Arrays.stream(values())
.filter(p -> p.getType().equals(type))
.findAny().orElse(null);
Assert.notNull(pirateEnum, "暂不支持的策略模式!");
return pirateEnum.getBeanName();
} PirateEnum(Integer type, String name, String beanName) {
this.type = type;
this.name = name;
this.beanName = beanName;
} public Integer getType() {
return type;
} public void setType(Integer type) {
this.type = type;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getBeanName() {
return beanName;
} public void setBeanName(String beanName) {
this.beanName = beanName;
}
}

⑤使用springBean工具类获取beanName

⑥使用

  • 需要注入工厂来调用方法即可
    @Resource
private StrategyByFactory strategyByFactory; @Test
public void test03()throws Exception{
//使用简单工厂生产的策略模式 —— 明显发现使用起来更简单,把创建bean的权利交给了简单工厂
IFactoryStrategy businessMap = strategyByFactory.getBusinessMap(33); System.out.println(businessMap.eating());
System.out.println(businessMap.play()); }

结果:

  • 传入:11

  • 传入:22

  • 传入:33

4、总结-工具类

Java设计模式-策略模式-基于Spring实现的更多相关文章

  1. java设计模式 策略模式Strategy

    本章讲述java设计模式中,策略模式相关的知识点. 1.策略模式定义 策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户.策略模式属于对象的 ...

  2. JAVA 设计模式 策略模式

    用途 Title 它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. 策略模式是一种行为型模式. 结构

  3. 我的Java设计模式-策略模式

    今天给大家说说田忌赛马的故事.如有雷同,纯属巧合!话说在战国时期,群雄割据,硝烟四起,茶余饭后还是少不了娱乐活动的,其中赛马是最火爆的.一天,孙膑看到田忌像个死鸡似的就知道肯定赛马又输给了齐威王,立马 ...

  4. Java设计模式-策略模式详解

    前言 在软件领域中,设计模式作为一种经典的开发实践常常需要我们去深入的理解,而策略模式作为设计模式的一种,使用频率也是相对来说比较高的,在Java中,当我们学习TreeSet集合的时候,就采用了经典的 ...

  5. Java 设计模式--策略模式,枚举+工厂方法实现

    如果项目中的一个页面跳转功能存在10个以上的if else判断,想要做一下整改 一.什么是策略模式 策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,最终可以实现解决 ...

  6. Java设计模式—策略模式

    1.策略模式(Strategy Pattern)是一种比较简单的模式,也叫做政策模式(PolicyPattern). 定义如下:     Define a family of algorithms,e ...

  7. java设计模式--策略模式

    策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 本文地址:http:// ...

  8. Java设计模式-策略模式(strategy)

    策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户.需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无 ...

  9. Java设计模式——策略模式

    策略模式的定义: 策略模式其实特别好理解,俗话说得好,条条大路通罗马,做的都是一件事,实现的方式却可以千万种,在这种情况下,如何使得每个人都可以根据自己的喜好来选择具体的方式,在调用时可以根据不同方式 ...

  10. Java设计模式-策略模式实际应用场景

    容错恢复机制        容错恢复机制是应用程序开发中非常常见的功能.那么什么是容错恢复呢?简单点说就是:程序运行的时候,正常情况下应该按照某种方式来做,如果按照某种方式来做发生错误的话,系统并不会 ...

随机推荐

  1. ERROR 1290 (HY000): The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement

    先执行: flush privileges; 再执行修改密码命令,可以了: set password for root@localhost=password('你的密码');

  2. C#调用HTTP POST请求上传图片

    public static string UploadImage(string uploadUrl, string imgPath, string fileparameter = "file ...

  3. Oracle字符串分隔函数

    记录一下 CREATE OR REPLACE TYPE str_split IS TABLE OF VARCHAR2 (4000); CREATE OR REPLACE FUNCTION splits ...

  4. 如何使用文件传输协议ftp,教你使用文件传输协议命令行

    FTP是文件传输协议的缩写.顾名思义,FTP用于在网络上的计算机之间传输文件.您可以使用文件传输协议在计算机帐户之间交换文件,在帐户和台式计算机之间传输文件或访问在线软件档案.但是请记住,许多文件传输 ...

  5. Ubuntu系统部署springcloud+nacos遇到的问题。

    1,部署上的jar包运行正常,但是通过浏览器不能访问,telnet +IP+端口连接不通.小皮面板访问后台接口也是不通但是小皮面板可以通过浏览器访问.具体问题暂未解决. 2,改用docker部署,将j ...

  6. 分享本人依照NOI大纲整理的CSPJ复习资料

    2023 CSP-J 复习文件 考纲 复习好 : 基础知识与编程环境 难度 计算机的基本构成 计算机的组成及功能 - 知乎 (zhihu.com) 操作系统的基本概念与常见操作 操作系统基础知识大汇总 ...

  7. #费马小定理#JZOJ 4015 数列

    题目 给出\(x_n=(ax_{n-1}^2+bx_{n-1}+c)\bmod m\) 给出\(x_0.a,b,c,n,m\),求\(x_n\) \(\text{Subtask 1:}n\leq 10 ...

  8. #线段树,离散#nssl 1476 联

    分析 由于下标过大,考虑离散,不仅仅是区间左右端点 假设只有一个区间从1到\(x\),那么修改后答案应该是\(x+1\) 所以说还要记录右端点+1的位置,你以为这就能A了吗 为了避免标记被覆盖,无论是 ...

  9. openGauss数据库源码解析——慢SQL检测

    openGauss 数据库源码解析--慢 SQL 检测 慢 SQL 检测的定义: 基于历史 SQL 语句信息进行模型训练,并用训练好的模型进行 SQL 语句的预测,利用预测结果判断该 SQL 语句是否 ...

  10. 「译文」深入了解Kubernetes和Nomad

    ️原文链接: https://www.cncf.io/blog/2023/10/23/introduction-a-closer-look-at-kubernetes-and-nomad/ ✍️作者: ...