策略模式的实现与应用:掌握灵活算法切换的技巧

文章目录

  • 常用的设计模式有以下几种:
    • 一.创建型模式(Creational Patterns):
    • 二.结构型模式(Structural Patterns):
    • 三.行为型模式(Behavioral Patterns):
    • 四.并发模式(Concurrent Patterns):
  • 策略模式概念
  • 一、策略模式例子一
  • 二、策略模式例子二
  • 三、策略模式例子三
  • 总结


常用的设计模式有以下几种:

**

一.创建型模式(Creational Patterns):

工厂模式(Factory Pattern)
抽象工厂模式(Abstract Factory Pattern)
单例模式(Singleton Pattern)
原型模式(Prototype Pattern)
建造者模式(Builder Pattern)

二.结构型模式(Structural Patterns):

适配器模式(Adapter Pattern)
桥接模式(Bridge Pattern)
装饰器模式(Decorator Pattern)
组合模式(Composite Pattern)
外观模式(Facade Pattern)
享元模式(Flyweight Pattern)
代理模式(Proxy Pattern)

三.行为型模式(Behavioral Patterns):

策略模式(Strategy Pattern)
观察者模式(Observer Pattern)
迭代器模式(Iterator Pattern)
命令模式(Command Pattern)
模板方法模式(Template Method Pattern)
职责链模式(Chain of Responsibility Pattern)
状态模式(State Pattern)
访问者模式(Visitor Pattern)
中介者模式(Mediator Pattern)
备忘录模式(Memento Pattern)
解释器模式(Interpreter Pattern)

四.并发模式(Concurrent Patterns):

单例模式(Singleton Pattern,在多线程环境下的应用)
生成器模式(Builder Pattern,在多线程环境下的应用)
保护性暂停模式(Guarded Suspension Pattern)
观察者模式(Observer Pattern,在多线程环境下的应用)

这些设计模式涵盖了对象的创建、对象间的组织和交互、以及对象的行为等方面,可以帮助开发者更好地组织和设计代码,提高代码的可扩展性、可维护性以及重用性。需要根据实际情况选择适合的设计模式来解决问题。**


策略模式概念

今天来讲一讲策略模式:
策略模式(Strategy Pattern)是一种行为设计模式,它允许你定义一系列算法,并将每个算法封装到独立的类中,使它们可以互相替换。策略模式使得算法的变化独立于使用它们的客户端。
在策略模式中,有一个上下文(Context)对象,它持有一个策略接口的引用,并通过调用策略接口的方法来执行具体的算法。算法类实现了策略接口,每个算法类都封装了一种具体的算法,客户端可以根据需要选择不同的策略对象,从而实现不同的行为。🤩🤩🤩
策略模式的优点包括:

1. 算法可以灵活地替换或新增,不影响使用算法的客户端。
2. 可以消除大量的条件语句,提高代码的可维护性和可读性。
3. 可以将算法的实现细节封装起来,提高代码的模块性和复用性。

策略模式在许多场景下都有应用,比如排序算法、计算费用、验证用户等。通过使用策略模式,可以优雅地处理复杂的逻辑,并提供一种可扩展、易于维护的解决方案。🤗🤗🤗

我并不喜欢看含义,对于这种概念性的东西,动手实践才是硬道理!
以下举出 策略模式 的几个 荔枝!!!😍😍😍
相信看完会更加理解策略模式的强大性!

在这里插入图片描述

一、策略模式例子一

假设我们正在开发一个商场收银系统,其中有不同的折扣策略供用户选择,包括无折扣、固定折扣和打折折扣。我们希望通过策略模式来实现这些不同的折扣策略。
首先,我们定义一个抽象的策略接口 DiscountStrategy,它声明了一个计算折扣金额的方法 calculateDiscount:

public interface DiscountStrategy {
    double calculateDiscount(double amount);
}

然后,我们分别实现三种具体的策略类:NoDiscountStrategy(无折扣)、FixedDiscountStrategy(固定折扣)和PercentageDiscountStrategy(打折折扣)。它们都实现了 DiscountStrategy 接口:

public class NoDiscountStrategy implements DiscountStrategy {
    @Override
    public double calculateDiscount(double amount) {
        return 0; // 无折扣,返回0
    }
}

public class FixedDiscountStrategy implements DiscountStrategy {
    private double discount;

    public FixedDiscountStrategy(double discount) {
        this.discount = discount;
    }

    @Override
    public double calculateDiscount(double amount) {
        return discount; // 固定折扣,直接返回固定的折扣金额
    }
}

public class PercentageDiscountStrategy implements DiscountStrategy {
    private double percentage;

    public PercentageDiscountStrategy(double percentage) {
        this.percentage = percentage;
    }

    @Override
    public double calculateDiscount(double amount) {
        return amount * percentage; // 打折折扣,根据折扣比例计算折扣金额
    }
}

最后,我们定义一个上下文类 Cashier,它持有一个 DiscountStrategy 的引用,并在结算时调用该策略的方法:

public class Cashier {
    private DiscountStrategy discountStrategy;

    public void setDiscountStrategy(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }

    public double calculateTotalWithDiscount(double amount) {
        double discount = discountStrategy.calculateDiscount(amount);
        return amount - discount;
    }
}

现在,我们可以使用策略模式来实现商场收银系统的折扣功能了。示例如下:

public class Main {
    public static void main(String[] args) {
        Cashier cashier = new Cashier();

        // 设置无折扣策略
        DiscountStrategy noDiscountStrategy = new NoDiscountStrategy();
        cashier.setDiscountStrategy(noDiscountStrategy);
        double total = cashier.calculateTotalWithDiscount(100);
        System.out.println("Total with no discount: " + total);

        // 设置固定折扣策略
        DiscountStrategy fixedDiscountStrategy = new FixedDiscountStrategy(20);
        cashier.setDiscountStrategy(fixedDiscountStrategy);
        total = cashier.calculateTotalWithDiscount(100);
        System.out.println("Total with fixed discount: " + total);

        // 设置打折折扣策略
        DiscountStrategy percentageDiscountStrategy = new PercentageDiscountStrategy(0.1);
        cashier.setDiscountStrategy(percentageDiscountStrategy);
        total = cashier.calculateTotalWithDiscount(100);
        System.out.println("Total with percentage discount: " + total);
    }
}

输出结果:

Total with no discount: 100.0
Total with fixed discount: 80.0
Total with percentage discount: 90.0

通过策略模式,我们可以灵活地选择不同的折扣策略,并在运行时动态地切换和应用这些策略,而不需要修改 Cashier 类的代码。这样,我们可以方便地添加新的折扣策略或修改现有策略的实现,而不会对其他部分产生影响。这样的设计符合开闭原则,增加了代码的可维护性和扩展性。

二、策略模式例子二

例子2:排序算法
假设我们正在设计一个排序工具,它可以根据用户选择的不同排序算法对数据进行排序。我们可以使用策略模式来实现不同的排序策略。
首先,我们定义一个排序策略接口 SortingStrategy,它声明了一个排序方法 sort:

public interface SortingStrategy {
    void sort(int[] array);
}

然后,我们分别实现两种具体的策略类:BubbleSortStrategy(冒泡排序)和 QuickSortStrategy(快速排序)。它们都实现了 SortingStrategy 接口:

public class BubbleSortStrategy implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        // 冒泡排序算法的具体实现
        // ...
    }
}

public class QuickSortStrategy implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        // 快速排序算法的具体实现
        // ...
    }
}

最后,我们定义一个上下文类 Sorter,它持有一个 SortingStrategy 的引用,并在排序时调用该策略的方法:

public class Sorter {
    private SortingStrategy sortingStrategy;

    public void setSortingStrategy(SortingStrategy sortingStrategy) {
        this.sortingStrategy = sortingStrategy;
    }

    public void sortArray(int[] array) {
        sortingStrategy.sort(array);
    }
}

现在,我们可以使用策略模式来实现排序工具了。示例如下:

public class Main {
    public static void main(String[] args) {
        Sorter sorter = new Sorter();

        // 使用冒泡排序策略
        SortingStrategy bubbleSortStrategy = new BubbleSortStrategy();
        sorter.setSortingStrategy(bubbleSortStrategy);
        int[] array = {5, 3, 8, 2, 1};
        sorter.sortArray(array);
        System.out.println("Sorted array using bubble sort:");
        for (int num : array) {
            System.out.print(num + " ");
        }
        System.out.println();

        // 使用快速排序策略
        SortingStrategy quickSortStrategy = new QuickSortStrategy();
        sorter.setSortingStrategy(quickSortStrategy);
        int[] array2 = {9, 4, 6, 2, 7};
        sorter.sortArray(array2);
        System.out.println("Sorted array using quick sort:");
        for (int num : array2) {
            System.out.print(num + " ");
        }
        System.out.println();
    }
}

输出结果:

Sorted array using bubble sort:
1 2 3 5 8 
Sorted array using quick sort:
2 4 6 7 9

通过策略模式,我们可以灵活地选择不同的排序策略,而不需要修改 Sorter 类的代码。这样,我们可以方便地添加新的排序策略或修改现有策略的实现,而不会对其他部分产生影响。

三、策略模式例子三

假设我们正在开发一个电商平台,针对不同的用户类型(普通用户、VIP用户、管理员),我们需要为其提供不同的登录方式。
首先,我们定义一个登录策略接口 LoginStrategy,它声明了一个登录方法 login:

public interface LoginStrategy {
    void login();
}

然后,我们分别实现三种具体的策略类:DefaultLoginStrategy(普通用户登录方式)、VIPLoginStrategy(VIP用户登录方式)和 AdminLoginStrategy(管理员登录方式)。它们都实现了 LoginStrategy 接口:

public class DefaultLoginStrategy implements LoginStrategy {
    @Override
    public void login() {
        System.out.println("使用用户名和密码登录");
        // 具体的登录逻辑
    }
}

public class VIPLoginStrategy implements LoginStrategy {
    @Override
    public void login() {
        System.out.println("使用手机号和密码登录");
        // 具体的登录逻辑
    }
}

public class AdminLoginStrategy implements LoginStrategy {
    @Override
    public void login() {
        System.out.println("使用管理员账号和密码登录");
        // 具体的登录逻辑
    }
}

最后,我们定义一个上下文类 LoginContext,它持有一个 LoginStrategy 的引用,并在登录时调用该策略的方法:

public class LoginContext {
    private LoginStrategy loginStrategy;

    public void setLoginStrategy(LoginStrategy loginStrategy) {
        this.loginStrategy = loginStrategy;
    }

    public void performLogin() {
        loginStrategy.login();
    }
}

现在,我们可以使用策略模式来为不同的用户类型提供不同的登录方式了。示例如下:

public class Main {
    public static void main(String[] args) {
        LoginContext loginContext = new LoginContext();

        // 普通用户登录
        LoginStrategy defaultLoginStrategy = new DefaultLoginStrategy();
        loginContext.setLoginStrategy(defaultLoginStrategy);
        loginContext.performLogin();

        // VIP用户登录
        LoginStrategy vipLoginStrategy = new VIPLoginStrategy();
        loginContext.setLoginStrategy(vipLoginStrategy);
        loginContext.performLogin();

总结

UU们,懂了嘛!!!😄😄😄
以下是实际开发中常用的几个例子,展示了策略模式的应用:

支付方式:
在电商平台上,用户可以选择不同的支付方式进行支付,比如支付宝、微信支付、银行卡支付等。这些支付方式都具备支付的功能,但其实现方式和支付逻辑可能有所不同。策略模式可以用于将不同的支付方式封装成不同的策略类,然后在运行时根据用户选择的支付方式来选择相应的策略进行支付。

缓存策略:
在系统开发中,我们经常会使用缓存来提高系统性能。不同的数据操作可能需要不同的缓存策略,比如基于时间的过期策略、基于LRU(Least
Recently Used)的淘汰策略、基于LFU(Least Frequently
Used)的淘汰策略等。策略模式可以用于封装不同的缓存策略为不同的策略类,然后在运行时选择相应的缓存策略进行数据操作。

图像处理:
在图像处理应用中,我们可能需要应用不同的滤镜或特效来处理图像,比如黑白滤镜、模糊滤镜、锐化滤镜等。这些滤镜都具备处理图像的功能,但实现方式和处理逻辑可能有所不同。策略模式可以用于将不同的滤镜或特效封装成不同的策略类,然后在运行时根据用户选择的滤镜或特效来选择相应的策略进行图像处理。

日志记录级别:
在日志记录应用中,不同的日志级别对应不同的日志输出方式,比如普通日志输出到控制台,警告日志输出到文件,错误日志发送邮件等等。策略模式可以用于封装不同的日志记录级别为不同的策略类,然后在运行时根据日志级别选择相应的策略进行日志记录。

这些都是在实际开发中常用的例子,策略模式可以帮助我们根据不同的条件和需求来选择相应的策略进行处理,提供了灵活性和扩展性。它可以将不同的策略封装起来,使客户端代码与具体策略的实现解耦,从而提高代码的可维护性和可测试性。
(注意:是不同的处理逻辑,如果你只是根据不同类型查数据库一张表的数据,那就没啥必要了)
不懂或者有什么错误的地方,欢迎评论区留言,俺可以再举更多的 荔枝~~~

@作者:加辣椒了吗?
简介:憨批大学生一枚,喜欢在博客上记录自己的学习心得,也希望能够帮助到你们!
在这里插入图片描述

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

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

相关文章

k8s使用helm部署Harbor镜像仓库并启用SSL

1、部署nfs存储工具 参照:https://zhaoll.blog.csdn.net/article/details/128155767 2、部署helm 有多种安装方式,根据自己的k8s版本选择合适的helm版本 参考:https://blog.csdn.net/qq_30614345/article/details/131669319 3、部署Harbo…

matplotlib从起点出发(4)_Tutorial_4_Lifecycle

1 一幅图像的生命周期 本教程旨在揭示使用matplotlib绘制的一幅图像的生命周期,包括它的开始、中间和结束。我们将从一些原始数据开始,最后保存自定义可视化的图形。在此过程中,我们尝试使用matplotlib突出一些简洁的功能和最佳实践。 2 关…

三子棋(超详解+完整码源)

三子棋 前言一,游戏规则二,所需文件三,创建菜单四,游戏核心内容实现1.棋盘初始化1.棋盘展示3.玩家下棋4.电脑下棋5.游戏胜负判断6.game()函数内部具体实现 四,游戏运行实操 前言 C语言实现三子棋…

maven

一、为什么需要使用maven 如今我们构建一个项目需要用到很多第三方的类库 ,例如我们在开发项目中 需要引入 这些依赖jar包 一个项目Jar包的数量之多往往让我们瞠目结舌,并且Jar包之间的关系非常复杂,一个Jar包往往又会引用其他Jar包&#x…

安全学习DAY07_其他协议抓包技术

协议抓包技术-全局-APP&小程序&PC应用 抓包工具-Wireshark&科来分析&封包 TCPDump: 是可以将网络中传送的数据包完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用…

stable diffusion如何确保每张图的面部一致?

可以使用roop插件,确定好脸部图片后,使用roop固定,然后生成的所有图片都使用同一张脸。 这款插件的功能简单粗暴:一键换脸。 如图所示: 任意上传一张脸部清晰的图片,点击启用。 在其他提示词不变的情况下…

赛多利斯Sartorius天平java后端对接

业务场景 要将赛多利斯天平的数据读出来解析并且显示到对应的数字框,支持一台设备连接多种精度的天平 后端实现 通过协议解析数据,然后将数据存储 详细代码就不贴了,感兴趣的可以私聊我

GPT-AI 使用的技术概览

ChatGPT 使用的技术概览 智心AI-3.5/4模型,联网对话,MJ快速绘画 从去年 OpenAI 发布 ChatGPT 以来,AI 的能力再次惊艳了世人。在这样的一个时间节点,重新去学习相关技术显得很有必要。 ChatGPT 的内容很多,我计划采用…

3ds Max图文教程: 创建致命的冠状病毒动画

推荐: NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 病毒建模 步骤 1 打开 3ds Max。 打开 3ds Max 步骤 2 在透视视口中创建一个半径为 50,线段为 20 的 GeoSphere。 创建地球 步骤 3 打开修改器列表并将置换修改器应用于地理 球。 置换…

Linux系统MySQL中用户的权限管理

本节主要学习用户权限管理的概述,用户权限类型,用户赋权,权限删除,用户删除等。 目录 一、概述 二、用户权限类型 三、用户赋权 四、权限删除 五、用户删除 一、概述 数据库用户权限管理是数据库系统中非常重要的一个方面&am…

Dockerfile 创建镜像,构建LNMP+wordpress架构

目录 一、Dockerfile 构建镜像 1.Dockerfile 构建 nginx镜像 1.1创建 nginx Dockerfile 目录 1.2编写 Dockerfile 文件 1.3构建nginx镜像 2.Dockerfile 构建 mysql 镜像 2.1创建 mysql Dockerfile 目录 2.2修改mysql配置文件 2.3编写 Dockerfile 文件 2.4构建mysql镜…

ChatGPT伦理挑战:人工智能的权利与责任

🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~&#x1f33…

全志F1C200S嵌入式驱动开发(触摸屏驱动)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 触摸屏一般有两种,一种是电阻触摸屏,一种是电容触摸屏。前者需要自己买一颗i2c的信号读取芯片,用的比较多的是ns2009。后者自身集成了读取芯片,用的比较多的是gt911。正好之前测…

(十三)定时任务

以下内容来自 尚硅谷,写这一系列的文章,主要是为了方便后续自己的查看,不用带着个PDF找来找去的,太麻烦! 第 13 章 定时任务 13.1 什么是定时任务 1、InfluxDB任务是一个定时执行的FLUX脚本,它先查询数据…

Docker啥是数据持久化?

文章目录 数据持久化数据卷相关命令创建读写数据卷创建只读数据卷数据卷共享数据卷容器实现数据卷共享nginx实现数据卷共享nfs总结 Dockerfile持久化Dockerfile方式docker run总结 数据持久化 ​ 在容器层的 UnionFS(联合文件系统)中对文件/目录的任何修…

SRC | 逻辑漏洞原理及实战

前言 作者简介:不知名白帽,网络安全学习者。 博客主页:不知名白帽_网络安全,CTF,内网渗透-CSDN博客 网络安全交流社区:https://bbs.csdn.net/forums/angluoanquan 目录 逻辑漏洞基础 概述 分类 URL跳转漏洞 概述 危害 漏洞…

Android:RecyclerView封装,打造列表极简加载

前言 mBinding.recycler.linear().divider().set<OrdinaryListBean> {addLayout(R.layout.layout_ordinary_item)}.setList(getList()) 如果我要说&#xff0c;除了数据和布局之外&#xff0c;以上的几行代码&#xff0c;就实现了一个列表加载&#xff0c;有老铁会相信…

Django学习笔记-表单(forms)的使用

在Django中提供了了form表单&#xff0c;可以更为简单的创建表单模板信息&#xff0c;简化html的表单。 一、网页应用程序中表单的应用 表单通常用来作为提交数据时候使用。 1.1 创建表单模板文件夹 在项目文件夹下创建一个template文件夹&#xff0c;用于存储所有的html模…

XCP详解「总目录」

目录 XCP详解「总目录」 1 概览 2 理论 3 实践 4 其他 XCP详解「总目录」 基础学习&#xff0c;慢慢补充 1 概览 2 理论 3 实践 XCP详解「3.1ASAP2新建A2L文件」 XCP详解「3.2CANape新建工程导入A2L」 XCP详解「3.3A2L信号添加和更新」 XCP详解「3.4CANape中新建A2L文…

学习 C语言第二天 :C语言数据类型和变量(下)

目录&#xff1a; 1.变量的介绍以及存储 2.算术操作符、赋值操作符、单目操作符 3.scanf和printf的介绍 1.变量的介绍以及存储 1.1.变量的创建 了解了什么是类型了&#xff0c;类型是用来创建变量的。 变量是什么呢&#xff1f;在C语言当中不经常变的量称为常量&#xff0c;经常…