策略模式与简单工厂模式:终结if-else混乱,让代码更清爽

2023-12-02 18:52

本文主要是介绍策略模式与简单工厂模式:终结if-else混乱,让代码更清爽,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

阅读建议

嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议:

  1. 本篇文章大概4500多字,预计阅读时间长需要5分钟。
  2. 本篇文章的实战性、理论性较强,是一篇质量分数较高的技术干货文章,建议收藏起来,方便时常学习与回顾,温故而知新。
  3. 创作不易,免费的点赞、关注,请走上一走,算是对博主一些鼓励,让我更有动力输出更多的干货内容。

前言

在软件开发过程中,我们常常面临着许多问题,其中之一就是如何有效地管理复杂的逻辑和流程。策略模式和工厂模式是两种非常实用的设计模式,可以帮助我们解决这些问题。本文将介绍策略模式和简单工厂模式的概念、实现和应用,并通过实例代码来演示它们的使用方法。

反面示例

需求描述

很多购物网站都有会员业务,不同等级的会员可以享受不同程度的优惠,不同类别的商品还有不同的打折优惠,这里假设只有会员优惠,会员等级有非会员、初级会员、中级会员、高级会员四个等级,其中非会员在支付的时候需要全额支付 ,初级会员可以享受9折优惠,中级会员可以享受8折优惠,高级会员可以享受6折优惠;如果需要写一个支付接口,需要怎么实现呢?

反面实现一

public Double actualPay(Double money) {String memberLevel = this.getMemberLevel();if ("初级".equals(memberLevel)) {money = money * 0.9;} else if ("中级".equals(memberLevel)) {money = money * 0.8;} else if ("高级".equals(memberLevel)) {money = money * 0.6;} else {money = money * 1;}return money;
}

需求变更

双十一举报大酬宾活动,如果购买商品总额超过300元,且小于400元,初级会员可以减免5元,中级会员可以减免8元,高级会员可以减免11元; 如果购买商品总额超过400元,且小于500元,初级会员可以减免10元,中级会员可以减免13元,高级会员可以减免16元; 如果购买商品总额超过500元,初级会员可以减免15元,中级会员可以减免18元,高级会员可以减免21元;

反面实现二

public Double actualPay(Double money) {String memberLevel = this.getMemberLevel();if ("初级".equals(memberLevel)) {money = money * 0.9;if (money > 300 && money <= 400) {money = money - 5;} else if (money > 400 && money <= 500) {money = money - 10;} else if (money > 500) {money = money - 15;}} else if ("中级".equals(memberLevel)) {money = money * 0.8;if (money > 300 && money <= 400) {money = money - 8;} else if (money > 400 && money <= 500) {money = money - 13;} else if (money > 500) {money = money - 18;}} else if ("高级".equals(memberLevel)) {money = money * 0.6;if (money > 300 && money <= 400) {money = money - 11;} else if (money > 400 && money <= 500) {money = money - 16;} else if (money > 500) {money = money - 21;}} else {money = money - 1;}return money;
}

反思总结

  1. 代码的可读性差。其他开发者在阅读此段代码时,需要花费一定的时间来理解每个条件。
  2. 维护性差。如果需求改变,例如增加一个新的折扣等级、新的活动内容,那么就需要修改这个if-else语句,可能会导致出错。
  3. 逻辑不清晰。这种if-else结构反复判断、嵌套很容易让人误解其意图,逻辑表现并不直观。

解决方案

策略模式与简单工厂模式

策略模式

策略模式是一种行为型设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式的主要目的是将算法的行为和环境分开,将一系列算法封装在策略类中,并在运行时根据客户端的需求选择相应的算法。策略模式适用于需要使用多种算法,且算法之间可以相互替换的情况。在策略模式中,算法的变化不会影响到使用算法的客户端。

简单工厂模式

简单工厂模式是一种属于创建型模式的设计模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式的核心是一个工厂类,它负责实现创建所有产品实例的内部逻辑。这个工厂类提供了一个或多个静态的工厂方法,根据参数的不同返回不同类的实例。这些被创建的实例通常都具有共同的父类。

实现原理

策略模式与简单工厂模式可以终结if-else混乱的工作原理是:通过封装算法和对象创建,使得代码更加模块化和可维护。

  • 策略模式定义了一组算法,每个算法都可以独立地替换和修改,而不需要影响其他代码。通过使用策略模式,我们可以将算法从if-else语句中分离出来,将算法的封装和实现交由具体的策略类来处理。这样,如果需要添加新的算法或修改现有算法,我们只需要创建新的策略类或修改现有策略类,而不需要在主程序中添加if-else语句。
  • 简单工厂模式提供了一种创建对象的接口,而不需要指定具体的类。通过使用简单工厂模式,我们可以将策略的创建和使用代码分离。具体来说,简单工厂模式可以根据输入参数或配置文件等信息来创建具体策略对象,并将具体策略对象的类型和使用方式交给调用方来处理。这样,我们可以在不修改原有代码的情况下,轻松地替换对象的具体实现。

实现步骤

1、定义抽象的支付策略接口:PayStrategy.java;

/*** 支付策略接口*/
public interface PayStrategy {/*** 实际支付金额计算* @param money*/Double compute(Double money);
}

2、定义具体的支付策略类:Level0Streategy.java、Level1Streategy.java、Level2Streategy.java、Level3Streategy.java

/*** 非会员计费策略*/
public class Level0Strategy implements PayStrategy{@Overridepublic Double compute(Double money) {System.out.println("非会员开始计费");return money;}
}
/*** 初级会员计费策略*/
public class Level1Strategy implements PayStrategy{@Overridepublic Double compute(Double money) {System.out.println("初级会员开始计费");return money*0.8;}
}

3、定义用于存储和传递策略的上下文:StreateContext.java

/*** 支付策略上下文*/
public class StrategyContent {private PayStrategy payStrategy;public StrategyContent(PayStrategy payStrategy) {this.payStrategy = payStrategy;}/*** 支付方法* @param money* @return*/public Double pay(Double money){return this.payStrategy.compute(money);}
}

4、定义策略工厂类,用于生产具体的策略:PayStreategyFactory.java

/*** 策略工厂*/
public class PayStrategyFactory {public static PayStrategy getStrategy(Member member){PayStrategy payStrategy;switch (member.getLevel()){case "初级":payStrategy=new Level1Strategy();break;case "中级":payStrategy=new Level2Strategy();break;case "高级":payStrategy=new Level3Strategy();break;default:payStrategy=new Level0Strategy();break;}return payStrategy;}
}

5、编写客户端:,模拟不同的用户进行支付:Test.java

public class ClientTest {public static void main(String[] args) {Member member = new Member("小明", "初级", 300.00);PayStrategy strategy = PayStrategyFactory.getStrategy(member);StrategyContent strategyContent = new StrategyContent(strategy);Double pay = strategyContent.pay(member.getPay());}
}

如何扩展

1、定义新的具体支付策略类来实现的抽象支付策略接口;

2、变更支付策略工厂的实现;

3、修改客户端业务;

反思总结

  1. 代码的可读性得到改善。具体的策略实现代替了原先的if分支判断,其他开发者在阅读此段代码时,通过不同的策略即可大概知道其逻辑。
  2. 维护性差。如果需求发生变更,只需要新增具体的策略实现即可,不会影响到其他已存在的策略,导致出错的概率大大降低。
  3. 通过过策略上下文,具体的支付金额计算与业务端解耦,逻辑更清晰。

是否还有其他解决方案?

  • 策略模式与抽象工厂模式
  • 策略模式与工厂方法模式

if-else真的干掉了吗?

当你以为一切都完美的解决的时候,实际上只是用一个方法解决了一个问题,然后又带来新的问题。新的问题是什么呢?

实际上在原先的if-else判断放到了策略工厂实现里了,面对新增的扩展需求,策略工厂的实现也是需要进行一定程度的修改的。如果实在不想修改,有没有解决方法?也有,那就是用抽象工厂代替简单工厂。是否有必要这样做,还需要结合具体的业务进行判断。

策略模式与简单工厂模式实际上并没有完全终止if-else的混乱,那么这么做还有意义吗?

当然有,业务端在调用时候,通过策略上下文类,实现了业务端调用逻辑与支付计算逻辑的解耦,由原来的乱糟糟一团,变成现在的几行代码,而且在后续的扩展上又提供了优秀灵活的扩展机制,一定程度上符合设计原则中的开闭原则,这就是意义。这里特别解释一下,一定程度上是指,需求的变更在实现上可以不影响原来的策略,但获取具体策略的逻辑需要一定程度修改。

这篇关于策略模式与简单工厂模式:终结if-else混乱,让代码更清爽的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/446421

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

redis群集简单部署过程

《redis群集简单部署过程》文章介绍了Redis,一个高性能的键值存储系统,其支持多种数据结构和命令,它还讨论了Redis的服务器端架构、数据存储和获取、协议和命令、高可用性方案、缓存机制以及监控和... 目录Redis介绍1. 基本概念2. 服务器端3. 存储和获取数据4. 协议和命令5. 高可用性6.

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

Deepseek使用指南与提问优化策略方式

《Deepseek使用指南与提问优化策略方式》本文介绍了DeepSeek语义搜索引擎的核心功能、集成方法及优化提问策略,通过自然语言处理和机器学习提供精准搜索结果,适用于智能客服、知识库检索等领域... 目录序言1. DeepSeek 概述2. DeepSeek 的集成与使用2.1 DeepSeek API

Redis的数据过期策略和数据淘汰策略

《Redis的数据过期策略和数据淘汰策略》本文主要介绍了Redis的数据过期策略和数据淘汰策略,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录一、数据过期策略1、惰性删除2、定期删除二、数据淘汰策略1、数据淘汰策略概念2、8种数据淘汰策略

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加