策略模式:优雅地实现可扩展的设计

策略模式:优雅地实现可扩展的设计

摘要: 策略模式是一种常用的设计模式,它可以帮助我们实现可扩展的、灵活的代码结构。本文将通过一个计算器案例来介绍策略模式的概念、使用场景以及如何在实际项目中应用策略模式来提高代码的可维护性和可扩展性。

引言

在软件开发中,我们经常会遇到需要根据不同的条件选择不同的算法或行为的情况。传统的做法是使用大量的if-else语句或switch语句来实现这种选择逻辑,但这样的代码结构往往难以维护和扩展。策略模式提供了一种优雅的解决方案,它将不同的算法或行为封装成独立的策略类,并通过一个上下文类来选择并执行相应的策略。

策略模式的概念

策略模式是一种行为型设计模式,它定义了一系列的算法或行为,并将其封装成独立的策略类。这些策略类可以互相替换,使得算法或行为的选择可以在运行时动态地改变。策略模式的核心思想是将算法或行为的选择与具体的实现分离,从而使得代码更加灵活、可维护和可扩展。

计算器案例

假设我们正在开发一个简单的计算器应用程序,该应用程序可以执行加法、减法、乘法和除法操作。传统的做法是使用if-else语句或switch语句来根据用户输入的操作符执行相应的操作。然而,这样的实现方式存在以下问题:

  1. 如果需要添加新的操作,就需要修改已有的代码,违反了开闭原则
  2. 如果需要修改某个操作的实现,就需要修改多处代码,增加了维护的难度。

下面我们将使用策略模式来重构这个计算器应用程序,使其更加灵活、可维护和可扩展。

策略模式的实现步骤

使用策略模式实现可扩展的代码结构可以分为以下几个步骤:
在这里插入图片描述

1. 定义策略接口

首先,我们需要定义一个策略接口,该接口声明了执行计算操作的方法。在我们的计算器案例中,我们可以将该接口命名为CalculatorStrategy,并声明一个calculate方法,用于执行具体的计算操作。

public interface CalculatorStrategy {
    double calculate(double num1, double num2);
}

2. 实现具体策略类

接下来,我们需要根据业务需求,实现具体的策略类。在我们的计算器案例中,我们可以实现加法、减法、乘法和除法四种策略类,分别对应不同的计算操作。

public class AdditionStrategy implements CalculatorStrategy {
    @Override
    public double calculate(double num1, double num2) {
        return num1 + num2;
    }
}

public class SubtractionStrategy implements CalculatorStrategy {
    @Override
    public double calculate(double num1, double num2) {
        return num1 - num2;
    }
}

public class MultiplicationStrategy implements CalculatorStrategy {
    @Override
    public double calculate(double num1, double num2) {
        return num1 * num2;
    }
}

public class DivisionStrategy implements CalculatorStrategy {
    @Override
    public double calculate(double num1, double num2) {
        if (num2 != 0) {
            return num1 / num2;
        } else {
            throw new IllegalArgumentException("Divisor cannot be zero");
        }
    }
}

3. 定义上下文类

然后,我们需要定义一个上下文类,该类持有一个策略接口的引用,并提供一个方法来设置和执行策略。在我们的计算器案例中,我们可以将该上下文类命名为CalculatorContext

public class CalculatorContext {
    private CalculatorStrategy strategy;

    public void setStrategy(CalculatorStrategy strategy) {
        this.strategy = strategy;
    }

    public double executeStrategy(double num1, double num2) {
        return strategy.calculate(num1, num2);
    }
}

4. 使用策略模式

最后,在客户端代码中,我们可以通过实例化上下文类并设置相应的策略,来实现不同的计算操作。

public class CalculatorApp {
        public static void main(String[] args) {
            CalculatorContext context = new CalculatorContext();

            // 使用加法策略
            context.setStrategy(new AdditionStrategy());
            double result = context.executeStrategy(10, 5);
            System.out.println("Addition: " + result);

            // 使用减法策略
            context.setStrategy(new SubtractionStrategy());
            result = context.executeStrategy(10, 5);
            System.out.println("Subtraction: " + result);

            // 使用乘法策略
            context.setStrategy(new MultiplicationStrategy());
            result = context.executeStrategy(10, 5);
            System.out.println("Multiplication: " + result);

            // 使用除法策略
            context.setStrategy(new DivisionStrategy());
            result = context.executeStrategy(10, 5);
            System.out.println("Division: " + result);
        }
}

在这里插入图片描述
策略模式在工作中的一个简单应用

策略模式的优点

策略模式具有以下优点:

  1. 策略模式将算法或行为的选择与具体的实现分离,使得代码更加灵活、可维护和可扩展
  2. 策略模式符合开闭原则,可以在不修改原有代码的情况下增加新的策略。
  3. 策略模式可以提高代码的复用性,不同的策略可以被多个上下文类共享使用。

策略模式的注意事项

在使用策略模式时需要注意以下事项:

  1. 策略模式适用于算法或行为之间相对独立的情况,如果算法或行为之间存在复杂的依赖关系,可能不适合使用策略模式
  2. 策略模式的上下文类需要持有一个策略接口的引用,因此需要在上下文类中进行策略的选择和设置。

结论

策略模式是一种优雅地实现可扩展的设计的方法。通过将算法或行为封装成独立的策略类,并通过上下文类来选择和执行策略,可以使得代码更加灵活、可维护和可扩展。在实际项目中,合理地应用策略模式可以提高代码的可维护性和可扩展性,使得系统更加稳定和可靠。

案例参考链接:

  1. Refactoring Guru - Strategy Pattern

学习更多设计模式

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

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

相关文章

[C++项目] Boost文档 站内搜索引擎(1): 项目背景介绍、相关技术栈、相关概念介绍...

项目背景 Boost库是C中一个非常重要的开源库. 它实现了许多C标准库中没有涉及的特性和功能, 一度成为了C标准库的拓展库. C新标准的内容, 很大一部分脱胎于Boost库中. Boost库的高质量代码 以及 提供了更多实用方便的C组件, 使得Boost库在C开发中会被高频使用 为方便开发者学…

设计模式行为型——备忘录模式

目录 什么是备忘录模式 备忘录模式的实现 备忘录模式角色 备忘录模式类图 备忘录模式举例 备忘录模式代码实现 备忘录模式的特点 优点 缺点 使用场景 注意事项 实际应用 什么是备忘录模式 备忘录模式(Memento Pattern)又叫做快照模式&#x…

qt源码---事件系统之QCoreApplication

上一节分析了qt和windows系统之间的消息的传递,本节着重看一下,qt内部的事件是如何传递的? 1.sendEvent函数 在使用的自定义事件时,有时需要手动抛出一个事件,常用的方式有2种,其一时阻塞式的sendEvent函…

在IDEA同一个窗口中同时打开多个独立项目

文章说明 本文主要说明如何在Intellij Idea中同时打开多个独立的Maven项目。 我在使用idea的时候,由于自己负责了很多项目,经常要在不通的代码之间切换来切换去。然后搜索代码的时候也只能搜到当前打开的这个项目。因为这个原因,一些小项目…

wxwidgets Ribbon使用wxRibbonToolBar实例

wxRibbonToolBar就是工具栏,一下是实现的效果,界面只是功能展示,没有美化 实现代码如下所示: MyFrame::MyFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(800, 600)) …

vue中点击添加类名,并且实现升降序

1.介绍 要求:掌握indexOf()用法;动态绑定类名的对象写法;iconfont使用;split()用法;三元运算符用法;es6模板字符串; 说明:首先综合元素默认有元素并且是降序。服务器传来的数据格式…

C++物理引擎Box2D的下载,编译,VS2013配置环境

文章目录 网站和下载地址编译工具:编译box2dhelloworld测试网站和下载地址 https://box2d.org/ 下载地址 https://hub.nuaa.cf/erincatto/box2d/tags 编译工具: 1.VS2013 2.cmake 下载地址 https://cmake.org/ 编译box2d 下载box2d源码2.4.0,解压。在box2d-2.4.0目录下…

什么是场景营销,小红书场景营销方式和方法有哪些

现在小红书上最流行的就是场景营销,那什么是场景营销,应该怎么做呢?今天来和大家分享下大家都在说得场景营销是什么,在小红书投放怎么做好场景营销? 一、什么是场景化营销 说白来,场景营销(Scene Marketing…

机器学习深度学习——从全连接层到卷积

👨‍🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习&&深度学习——非NVIDIA显卡怎么做深度学习(坑点排查) 📚订阅专栏:机器…

Python测试框架pytest:测试用例、查找子集、参数化、跳过

Pytest是一个基于python的测试框架,用于编写和执行测试代码。pytest主要用于API测试,可以编写代码来测试API、数据库、UI等。 pytest是一个非常成熟的全功能的Python测试框架,主要有以下几个优点: 简单灵活,容易上手。…

react搭建在线编辑html的站点——引入grapes实现在线拖拉拽编辑html

文章目录 ⭐前言⭐搭建react ts项目⭐引入grapes 插件⭐结束 ⭐前言 大家好,我是yma16,本文分享关于react搭建在线编辑html的站点。 react 发展历史 React是由Facebook开发的一种JavaScript库,用于构建用户界面。React最初发布于2013年&…

没有配置redis但是报错连接redis失败

问题 没有配置redis但是报错连接redis失败 检查maven配置是否引入了redis依赖(可能是传递依赖,最好检查引进来的公共工程 解决办法 只需要在该工程application.yml文件中配置一下 redis就好,或者移除redis依赖 spring:redis:password: hos…

一文了解 Android Auto 车载开发~

作者:牛蛙点点申请出战 背景 我的的产品作为一个海外音乐播放器,在车载场景听歌是一个很普遍的需求。在用户反馈中,也有很多用户提到希望能在车上播放音乐。同时车载音乐也可以作为提升用户消费时长一个抓手。 出海产品,主要服务…

【Vue】Parsing error: No Babel config file detected for ... vue

报错 Parsing error: No Babel config file detected for E:\Study\Vue网站\实现防篡改的水印\demo02\src\App.vue. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files.             …

玩机搞机---安卓新机型payload.bin刷写救砖 无需专用线刷包

目前的新机型官方卡刷包解包后都是payload.bin分区格式的卡刷固件。而有个别一些机型没有线刷包,当这些机型出现系统问题的时候有以下几种方法参考救砖。遇到类似故障的朋友可以借鉴参考下. 其中的不足和相关的资源可以参考这两个博文。任何教程的目的只是拓展你的…

反射调用private方法的坑

使用反射调用私有方法时,发现空指针异常,无法直接注入导致空指针异常 加入如下代码后,恢复正常 if (AopUtils.isCglibProxy(marketSmsTaskService)) {// 如果是cglib代理对象,则转为原始对象marketSmsTaskService (MarketSmsTas…

SpringBoot3基础用法

技术和工具「!喜新厌旧」 一、背景 最近在一个轻量级的服务中,尝试了最新的技术和工具选型; 即SpringBoot3,JDK17,IDEA2023,Navicat16,虽然新的技术和工具都更加强大和高效,但是适应采坑的过程…

React安装ant design组件库,并使用

ant design是一个很棒的组件库,官方地址:快速上手 - Ant Design 但是如何在React里面用起来,好像并不是很顺畅,没有像Vue里面那么友好,因为我踩过这个坑,虽然安装很简单,但是想要出样式&#x…

地球人口承载力估计 解析和C++代码

Description 假设地球上的新生资源按恒定速度增长。照此测算,地球上现有资源加上新生资源可供x亿人生活a年,或供y亿人生活b年。 为了能够实现可持续发展,避免资源枯竭,地球最多能够养活多少亿人? Input 一行&#xf…

[数据分析与可视化] Python绘制数据地图4-MovingPandas入门指北

MovingPandas是一个基于Python和GeoPandas的开源地理时空数据处理库,用于处理移动物体的轨迹数据。它提供了一组强大的工具,可以轻松地加载、分析和可视化移动物体的轨迹。通过使用MovingPandas,用户可以轻松地处理和分析移动对象数据&#x…