设计模式——行为型模式——策略模式

策略模式

定义

        策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。

        策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

        考虑如下场景:去旅游选择出行方式时,可以骑自行车、坐汽车、坐火车、坐飞机,在不考虑使用策略模式的时候使用if elseif else语句进行判断,此时代码中存在大量条件判断语句,代码不便于增强,不符合开闭原则。将其修改为策略模式可以去掉代码中大量的if判断语句,同时增强代码的可扩展性。

组成和UML图

策略模式的组成

  • 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。

  • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。

  • 环境(Context)类:持有一个策略类的引用,最终给客户端调用。

策略模式的UML图

代码示例

        促销活动:一家百货公司在定年度的促销活动。针对不同的节日(春节、中秋节、圣诞节)推出不同的促销活动,由促销员将促销活动展示给客户。类图如下:

        代码实现:以下示例代码仅仅是一个示例,便于理解策略模式,根据我的实习经验具体公司代码中策略模式不会这样使用的。【最近时间太紧,后期会梳理一下在实习中碰到的公司代码使用策略模式的例子,并更新以下代码示例】

package com.scut.adapter.strategy;

// 定义抽象策略类
public interface Strategy {
    void show();
}

package com.scut.adapter.strategy;
// 策略实现类A
public class StrategyA implements Strategy{
    @Override
    public void show() {
        System.out.println("中秋节活动,赠送中秋大礼包...");
    }
}

package com.scut.adapter.strategy;

// 策略实现类B
public class StrategyB implements Strategy{
    @Override
    public void show() {
        System.out.println("充值一百,送二百...");
    }
}

package com.scut.adapter.strategy;

// 策略实现类C
public class StrategyC implements Strategy{
    @Override
    public void show() {
        System.out.println("圣诞节活动,赠送水果大礼盒一套...");
    }
}

package com.scut.adapter.strategy;

// 定义售卖员,策略上下文类
public class SaleMan {
    private Strategy strategy;

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

    public Strategy getStrategy() {
        return strategy;
    }

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

package com.scut.adapter.strategy;

// 定义客户端、测试类
public class Client {
    public static void main(String[] args) {
        SaleMan saleMan = new SaleMan(new StrategyA());
        saleMan.saleShow();
        System.out.println("====================");
        saleMan.setStrategy(new StrategyB());
        saleMan.saleShow();
        System.out.println("====================");
    }
}
策略模式优缺点

优点:

  • 策略类之间可以自由切换

    由于策略类都实现同一个接口,所以使它们之间可以自由切换。

  • 易于扩展

    增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“

  • 避免使用多重条件选择语句(if else),充分体现面向对象设计思想。

缺点:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。

  • 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。

使用场景
  • 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。

  • 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。

  • 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。

  • 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构。

  • 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。

JDK中使用策略模式示例

        在Arrays类中的 sort() 方法中的Comparator使用的就是策略模式,具体源码可以自行查找以下。

参考文档

策略模式介绍及其具体使用场景_策略模式应用场景-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【ARM Cortex-M3指南】3:Cortex-M3基础

文章目录 三、Cortex-M3基础3.1 寄存器3.1.1 通用目的寄存器 R0~R73.1.2 通用目的寄存器 R8~R123.1.3 栈指针 R133.1.4 链接寄存器 R143.1.5 程序计数器 R15 3.2 特殊寄存器3.2.1 程序状态寄存器3.2.2 PRIMASK、FAULTMASK和BASEPRI寄存器3.2.3 控制寄存器 3.3 操作模式3.4 异常…

# 在 Windows 命令提示符(cmd)中,可以通过以下方法设置长命令自动换行

在 Windows 命令提示符(cmd)中,可以通过以下方法设置长命令自动换行 1、点击 cmd 窗口左上角标题栏,选择【属性】。 2、在【属性】菜单中,依次点击【选项】,找到【编辑选项】下面的【自动换行】&#xff…

经纬度聚类:聚类算法比较

需求: 将经纬度数据,根据经纬度进行聚类 初始数据 data.csv K均值聚类 简介 K均值(K-means)聚类是一种常用的无监督学习算法,用于将数据集中的样本分成K个不同的簇(cluster)。其基本思想是…

OpenCV | 入门

OpenCV | 入门 安装 参考教程 基础知识 V G A 640 480 VGA 640 \times 480 VGA640480 H D 1280 720 HD 1280 \times 720 HD1280720 F H D 1920 1080 FHD 1920 \times 1080 FHD19201080 4 K 3840 2160 4K 3840 \times 2160 4K38402160 这些都表示了固定的像素…

AI-数学-高中52-离散型随机变量概念及其分布列、两点分布

原作者视频:【随机变量】【一数辞典】2离散型随机变量及其分布列_哔哩哔哩_bilibili 离散型随机变量分布列:X表示离散型随机变量可能在取值,P:对应分布在概率,P括号里X1表示事件的名称。 示例:

机器学习的指标评价

之前在学校的小发明制作中,在终期答辩的时候,虽然整个项目的流程都答的很流畅。 在老师提问的过程中,当老师问我recall,precision,accuracy等指标是如何计算的,又能够表示模型的哪方面指标做得好。我听到这个问题的时候&#xff…

使用FPGA实现串-并型乘法器

介绍 其实我们知道,用FPGA实现乘法器并不是一件很简单的事,而且在FPGA中也有乘法器的IP核可以直接调用,我这里完全就是为了熟悉一些FPGA的语法然后写了这样一个电路。 串-并型乘法器模块 从字面上看,串-并乘法器就是其中一个乘数…

深入学习Redis(1):Redis内存模型

Redis的五个对象类型 字符串,哈希,列表,集合,有序集合 本节有关redis的内存模型 1.估算redis的内存使用情况 目前内存的价格比较的高,如果对于redis的内存使用情况能够进行计算,就可以选用合适的设备进…

初识webpack项目

新建一个空的工程 -> % mkdir webpack-project 为了方便追踪执行每一个命令,最终产生了哪些变更,将这个空工程初始化成git项目 -> % cd webpack-project/-> % git init Initialized empty Git repository in /Users/lixiang/frontworkspace/…

多级留言/评论的功能实现——SpringBoot3后端篇

目录 功能描述数据库表设计后端接口设计实体类entity 完整实体类dto 封装请求数据dto 封装分页请求数据vo 请求返回数据 Controller控制层Service层接口实现类 Mapper层Mybatis 操作数据库 补充:返回的数据结构自动创建实体类 最近毕设做完了,开始来梳理…

https自签名ssl证书生成流程

准备工作: 0.安装完整版的openssl openssl下载官网 安装到C:\OpenSSL32,也可以安装到其它盘,不要包含空格和中文 打开openssl.exe所在目录如:C:\OpenSSL32\bin,输入cmd.exe打开cmd控制台 1.创建ca文件夹 ,证书文件夹 mkdir …

二维泊松方程(三角形区域)Matlab有限元编程求解|案例源码+说明文本

专栏导读 作者简介:工学博士,高级工程师,专注于工业软件算法研究本文已收录于专栏:《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现,并提供所有案例完整源码;2.单元…

【Linux 进程】 自定义shell

目录 关于shell 1.打印提示符&&获取用户命令字符​编辑 2.分割字符串 3.检查是否为内建命令 cd命令 export命令 echo命令 1.输出最后一个执行的命令的状态退出码(返回码) 2.输出指定环境变量 4.执行外部命令 关于shell Shell 是计算机操…

C语言数组介绍

文章目录 一、数组的概念二、一维数组1.一维数组的创建2.一维数组的初始化3.数组的类型4.一维数组的使用5.一维数组在内存中的存储6.sizeof计算数组元素个数 三、二维数组1.二维数组的概念2.二维数组的创建3.二维数组的初始化4.二维数组的使用5.二维数组的输入和输出6.二维数组…

【教学类-50-09】20240505“数一数”图片样式09:数一数(几何图案——透明颜色重叠+纯黑边框+黑框粗细)

背景需求: 【教学类-50-03】20240408“数一数”图片样式03:透明图形与边框不相交,透明图形和其他透明图形重叠-CSDN博客文章浏览阅读867次,点赞28次,收藏25次。【教学类-50-03】20240408“数一数”图片样式03&#xf…

银行ETL-监管报送

1104报表 1104报表主要包括:资产负债,表外业务、流动性风险、贷款质量、投向行业和地区、重点客户等。 1104报表分类 普通报表、机构特色类报表。 反洗钱 大额交易、可疑交易。标签分类:疑似犯罪、疑似毒品、疑似传销。 反洗钱—接口报…

tomcat+maven+java+mysql图书管理系统2-完善项目结构,添加相关依赖

1.创建java目录 接着选择java&#xff0c;回车&#xff0c;则创建成功&#xff0c;成功后在左侧栏能看见 2.修改pom.xml文件,(添加依赖) <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…

pandas读取文件导致jupyter内核崩溃如何解决

读取execl文件出现以下问题: str_name "D:\\cao_use\\2017_2021(new).xlsx" train_df pd.read_excel(str_name, usecols[0])崩溃的指示图如下所示: bug原因:读入的文件太大&#xff0c;所需时间过长&#xff0c;在读取的过程中&#xff0c;使用中断按钮暂停会直…

mac监听 linux服务器可视化(Grafana+Promethus+Node_exporter)

Grafana和promethus(普罗米修斯)的安装和使用 监控系统的Prometheus类似于一个注册中心&#xff0c;我们可以只需要配置一个Prometheus,而在其他服务器&#xff0c;只需要安装node_exporter,它们的数据流转就是通过exporter采集数据信息&#xff0c;然后告诉prometheus它的位置…