策略模式(二十五)

news2024/11/24 20:40:07

相信自己,请一定要相信自己

上一章简单介绍了状态模式(二十四), 如果没有看过, 请观看上一章

一. 策略模式

引用 菜鸟教程里面 策略模式介绍: https://www.runoob.com/design-pattern/strategy-pattern.html

在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。

这种类型的设计模式属于行为型模式。

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

策略对象改变 context 对象的执行算法。

一.一 介绍

意图: 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

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

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

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

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

应用实例:

1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。

2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。

3、JAVA AWT 中的 LayoutManager。

优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。

缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。

使用场景:

1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

2、一个系统需要动态地在几种算法中选择一种。

3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项: 如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。


组成角色具体关系
抽象策略角色 (Strategy)FlyBehavior这个是一个抽象的角色,通常情况下使用接口或者抽象类去实现
具体策略角色NoFly, BadFly包装了具体的算法和行为
环境角色(Context)DuckContext内部会持有一个抽象角色的引用,给客户端调用

image-20230615202611911

二. 策略模式实例

二.一 飞实例一

二.一.一 抽象策略角色 FlyBehavior

public interface FlyBehavior {
    void fly();
}

二.一.二 具体策略

飞得好:

@Slf4j
public class GoodFly implements FlyBehavior{

    @Override
    public void fly() {
        log.info("飞的非常好");
    }
}

飞得差:

@Slf4j
public class BadFly implements FlyBehavior{

    @Override
    public void fly() {
        log.info("飞的很差");
    }
}

不会飞:

@Slf4j
public class NoFly implements FlyBehavior{

    @Override
    public void fly() {
        log.info("不能飞");
    }
}

二.一.三 环境角色和实现 AbstractDuckContext

@Slf4j
@Data
public abstract class AbstractDuckContext {
    private FlyBehavior flyBehavior;


    public AbstractDuckContext (FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }

    /**
     定义了公共的方法
     */
    public void speak(){
        log.info("可以叫");
    }

    public void swim() {
        log.info("可以游泳");
    }

    public void fly() {
        if (flyBehavior != null) {
            flyBehavior.fly();
        }
    }

}
public class TianE extends AbstractDuckContext {

    public TianE(FlyBehavior flyBehavior){
        super(flyBehavior);
    }
}

二.一.四 客户端调用

@Test
    public void oneTest() {
        AbstractDuckContext tianE = new TianE(new GoodFly());
        tianE.fly();
        log.info(">>>>> 这只天鹅受伤了");
        // 设置一下
        tianE.setFlyBehavior(new BadFly());
        tianE.getFlyBehavior().fly();
        log.info(">>>>> 这只天鹅翅膀被人打断了");
        tianE.setFlyBehavior(new NoFly());
        tianE.getFlyBehavior().fly();
    }

image-20230615203331025

二.二 计算方式策略

二.二.一 抽象角色 CalcStrategy

public interface CalcStrategy {

    int calc(int num1, int num2);
}

二.二.二 具体角色实现

相加:

public class AddStrategy implements CalcStrategy{

    @Override
    public int calc(int num1, int num2) {
        return num1 + num2;
    }
}

相减:

public class SubStrategy implements CalcStrategy{

    @Override
    public int calc(int num1, int num2) {
        return num1 - num2;
    }
}

二.二.三 上下文处理 CalcStrategyContext

public class CalcStrategyContext {

    private CalcStrategy calcStrategy;
    public CalcStrategyContext (CalcStrategy calcStrategy) {
        this.calcStrategy = calcStrategy;
    }

    public void setCalcStrategy(CalcStrategy calcStrategy) {
        this.calcStrategy = calcStrategy;
    }

    // 定义原先的方法
    public int calc(int num1, int num2) {
        return this.calcStrategy.calc(num1,num2);
    }
}

二.二.四 客户端调用

@Test
public void twoTest() {
    CalcStrategyContext calcStrategyContext = new CalcStrategyContext(new AddStrategy());
    int calc = calcStrategyContext.calc(5, 1);
    log.info(">>> 加法: {}", calc);

    calcStrategyContext.setCalcStrategy(new SubStrategy());
    calc = calcStrategyContext.calc(5, 1);
    log.info(">>> 减法: {}", calc);
}

INFO [main] (StrategyTest.java:36) - >>> 加法: 6
INFO [main] (StrategyTest.java:40) - >>> 减法: 4


本章节的代码放置在 github 上:


https://github.com/yuejianli/DesignPattern/tree/develop/Strategy


谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/652186.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MySQL函数】:让你的数据库操作更高效(二)

前言 ✨欢迎来到小K的MySQL专栏,本节将为大家带来MySQL日期时间、条件判断、系统信息、加密、进制转换和IP地址转换函数的讲解✨ 目录 前言一、日期和时间函数二、条件判断函数三、系统信息函数四、加密函数五、进制转换函数六、IP地址转换函数七、总结 一、日期和时…

chatgpt赋能python:Python怎么直接打出两个括号?

Python怎么直接打出两个括号? 你是否曾经在使用Python编写代码时,需要频繁地输入括号?每次都需要输入Shift键和9/0键来输入左右两个括号,有时还会出现输入错误的情况。那么有没有一种更加快捷的方法来输入括号呢?答案…

【Python 随练】企业奖金计算器

题目: 企业发放的奖金根据利润提成。利润 : 低于或等于 10 万元时,奖金可提 10%;高于 10 万元,低于 20 万元时,低于 10 万元的部分按 10%提成,高于 10万元的部分,可提成7.5%&#…

PCIe卡设计方案:单路12Gsps 3G 带宽模拟信号源PCIe卡

一、板卡概述 单路3G带宽模拟信号源卡由DA子卡和PCIe底板组成,二者通过标准FMC连接器互联,可以实现将PCIe总线数据转换为一路高速的模拟量输出。北京太速科技板可广泛用于雷达、通信、光电领域的噪声信号、毛刺、脉冲信号模拟产生等领域。 二、 …

程序的性能优化实践总结——JAVA

文章目录 1、 衡量程序性能的指标2、Java 程序性能优化切入点3、获取程序的性能数据1、nmon:获取系统性能数据2、jvisualvm:获取JVM性能数据3、jmc:获取Java应用详细性能数据4、arthas:获取单个请求的调用链耗时5、wrk获取Web接口的性能数据 4、应用程序优化1、缓冲区2、缓存3、…

mlr3系列机器学习教程1–mlr3介绍.

mlr3包是既往mlr包的升级,mlr3包为大量的机器学习技术提供了一个通用的技术接口。mlr3不单单是一个包,而是一个生态系列,包括一系列机器学习的R包。 我们下导入mlr3包,使用R自带的汽车数据来做个简单的演示 library(mlr3) libra…

Nodejs一、初识

零、文章目录 Nodejs一、初识 1、初识 Node.js (1)回顾与思考 浏览器中的 JavaScript 的组成部分 为什么 JavaScript 可以在浏览器中被执行 为什么 JavaScript 可以操作 DOM 和 BOM 浏览器中的 JavaScript 运行环境 JavaScript 能否做后端开发&#…

HTMLCSS Day07 CSS Flex布局

文章目录 1.flex布局2.flex布局属性容器属性元素属性 3.flex弹性盒模型3.1.主轴3.2.沿主轴的排列处理3.3.flex-flow属性3.4.justify-content属性3.5.align-items属性3.6.align-content3.7 项目属性3.8.order3.9.flex-grow3.10.flex-shrink3.11.flex-basis3.12.flex3.13.align-s…

干翻Mybatis源码系列之第十篇:Mybatis拦截器基本开发、基本使用和基本细节分析

给自己的每日一句 不从恶人的计谋,不站罪人的道路,不坐亵慢人的座位,惟喜爱耶和华的律法,昼夜思想,这人便为有福!他要像一棵树栽在溪水旁,按时候结果子,叶子也不枯干。凡他所做的尽…

使用终极 GUI 框架 NiceGUI 提升你的 Python 应用程序

介绍 随着机器学习和深度学习网站应用程序的快速增长,开发人员一直在寻找新的 Web 框架,以便更轻松地构建这些网站应用程序。 数据科学应用程序的普及程度已经上升,因此新的框架也在增加。开发人员创建了许多新的框架,这些框架被证…

【压缩技巧】如何把文件压缩成RAR?如何解压?

在生活及工作中,我们经常需要压缩文件使其更方便存储或传送。 压缩文件的格式有很多种,RAR是其中一种常见的格式,也是WinRAR软件独有的压缩格式。所以想要把文件压缩成RAR,就可以通过WinRAR来操作。 压缩方法如下: 1…

数组的原型方法-es6

数组的原型方法-es6Array.form()Array.of() find() 和 findIndex()copyWithin()fill()entries(),keys()和values()includes()flat()和flatMap()扩展运算符at()reduce()和reduceRight()some()判断数组中是否存在满足条件的项 18、Array.form() Array.from方法用于将两类对象转…

linuxOPS系统服务_linux高级命令

find命令 find 路径 [选项 选项的值] … 选项作用-name根据文件的名称进行-type按文件类型进行搜索,f代表普通文件,d代表文件夹 find命令查找文件 示例1 查找一个文件 案例1 ,在linux整个系统中查找 test.txt文件 find / -name test.txt -type f案例…

《Opencv3编程入门》学习笔记—第六章

《Opencv3编程入门》学习笔记 记录一下在学习《Opencv3编程入门》这本书时遇到的问题或重要的知识点。 第六章 图像处理 一、线性滤波:方框滤波、均值滤波、高斯滤波 (一)平滑处理 平滑处理也称模糊处理,是一种简单且使用频率…

像拿快递一样取文件的FileCodeBox

本文大约完成于 2月中旬,镜像中途有过更新; 什么是 FileCodeBox ? FileCodeBox 中文名是 文件快递柜,取文件像取快递一样,支持通过匿名口令分享文本,文件。 很多时候,我们都想将一些文件或文本传…

流量卡和手机上显示的流量对不上,这是怎么回事呢?

很多朋友反映,自己购买的流量卡和手机上显示的流量对不上,这到底是怎么回事呢?小编认为,如果出现这种情况,无非有两种因素: ​ 一、买了不正规的流量卡,也就是大家所说的物联卡。 物联卡的特点…

低压电源系统中防雷浪涌保护器的布局方案

低压电源系统是工业、商业和住宅领域中广泛应用的电力系统,其供电电压一般在1000V以下。由于雷击和浪涌等自然灾害的存在,低压电源系统需要防雷浪涌保护器来保护系统不受损坏。本文将详细介绍低压电源系统中防雷浪涌保护器的布置位置与规范。 防雷浪涌保…

AUTOSAR】UDS协议的代码分析与解读(八)----UDS安全访问27h和通讯控制28h

8.9 安全访问 Security Access (27h) 由于保密、排放或安全的原因, 安全访问服务提供一种方法以方便访问受限制的数据或诊断服务。 支持安全访问的ECU应该实现种子和密钥的合理算法,该算法应在特定文档中记录,而只有特定的少数 人可以访问该文…

FasterTransformer 003: CMAKELIST in gemm_test

cmake -DSM60 -DCMAKE_BUILD_TYPERelease .. -DCMAKE_BUILD_TYPE cmake编译类型通常默认为debug,但是在编译软件时,一般都需要使用release版本的,debug太慢了。设置为release版本可以在cmake文件里进行,也可以在运行cmake命令时使…

深度学习实践篇[17]:模型压缩技术、模型蒸馏算法:Patient-KD、DistilBERT、DynaBERT、TinyBERT

【深度学习入门到进阶】必看系列,含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、序列模型、预训练模型、对抗神经网络等 专栏详细介绍:【深度学习入门到进阶】必看系列,含激活函数、优化策略、损失函数、模型调优、归一化…