问题:通过策略模式+工厂模式+模板方法模式实现ifelse优化

news/2025/2/13 5:48:51/

项目场景:

提示:这里简述项目相关背景:

示例:商城系统有会员系统,不同会员有不同优惠程度,普通会员不优惠;黄金会员打8折;白金会员优惠50元,再打7折;


问题描述

提示:这里描述项目中遇到的问题:

例如:不同会员处理过程中,业务场景复杂,每种会员的业务逻辑很长,不方便维护。

public static double quote(String type) {double score = 1000;double res = 0;if (type.equals("1")) {res = score;} else if (type.equals("2")) {res = score - 50;} else if (type.equals("3")) {res = score * 0.8;} else if (type.equals("4")) {res = (score - 50) * 0.7;}return res;}

原因分析:

提示:这里填写问题的分析:

业务复杂


解决方案:

在这里插入图片描述

提示:这里填写该问题的具体解决方案:

package com.geekmice.springbootmybatiscrud.strategy.third;import java.math.BigDecimal;public interface PayStrategy {/*** 计算费用** @param price* @date 2025-02-10*/BigDecimal quote(BigDecimal price);
}

具体策略1:非会员,没有优惠

package com.geekmice.springbootmybatiscrud.strategy.third;import java.math.BigDecimal;public class OrdinaryStrategy implements PayStrategy{@Overridepublic BigDecimal quote(BigDecimal price) {return price;}
}

具体策略2:黄金会员,打八折

package com.geekmice.springbootmybatiscrud.strategy.third;import java.math.BigDecimal;
import java.util.Objects;public class GoldStrategy implements PayStrategy{@Overridepublic BigDecimal quote(BigDecimal price) {BigDecimal res = price.multiply(new BigDecimal("0.8"));return res;}
}

具体策略3:白银会员,先优惠50,后打七折

package com.geekmice.springbootmybatiscrud.strategy.third;import com.geekmice.springbootmybatiscrud.strategy.first.Strategy;import java.math.BigDecimal;public class PlatinumStrategy implements PayStrategy {@Overridepublic BigDecimal quote(BigDecimal price) {BigDecimal res = price.subtract(new BigDecimal("50")).multiply(new BigDecimal("0.7"));return res;}
}

上下文对象:持有一个Strategy的引用

package com.geekmice.springbootmybatiscrud.strategy.third;import java.math.BigDecimal;/*** @author Administrator*/
public class PayContext {private PayStrategy payStrategy;public void setStrategy(PayStrategy payStrategy) {this.payStrategy = payStrategy;}public BigDecimal getPrice(BigDecimal price) {if (payStrategy != null) {return payStrategy.quote(price);}return null;}
}

测试使用

package com.geekmice.springbootmybatiscrud.strategy.third;import java.math.BigDecimal;public class Demo {public static void main(String[] args) {PayContext payContext = new PayContext();OrdinaryStrategy ordinaryStrategy = new OrdinaryStrategy();payContext.setStrategy(ordinaryStrategy);System.out.println("普通会员:"+payContext.getPrice(new BigDecimal("100")));GoldStrategy goldStrategy = new GoldStrategy();payContext.setStrategy(goldStrategy);System.out.println("黄金会员:"+payContext.getPrice(new BigDecimal("100")));PlatinumStrategy platinumStrategy = new PlatinumStrategy();payContext.setStrategy(platinumStrategy);System.out.println("白银会员:"+payContext.getPrice(new BigDecimal("100")));}
}

结果

普通会员:100
黄金会员:80.0
白银会员:35.0

优化1:新增其他策略,不影响现有的策略

思路:新增策略类,实现策略接口

package com.geekmice.springbootmybatiscrud.strategy.third;import java.math.BigDecimal;public class SilverStrategy implements PayStrategy{@Overridepublic BigDecimal quote(BigDecimal price) {return price.subtract(new BigDecimal("50"));}
}package com.geekmice.springbootmybatiscrud.strategy.third;import java.math.BigDecimal;public class Demo {public static void main(String[] args) {PayContext payContext = new PayContext();OrdinaryStrategy ordinaryStrategy = new OrdinaryStrategy();payContext.setStrategy(ordinaryStrategy);System.out.println("普通会员:"+payContext.getPrice(new BigDecimal("100")));GoldStrategy goldStrategy = new GoldStrategy();payContext.setStrategy(goldStrategy);System.out.println("黄金会员:"+payContext.getPrice(new BigDecimal("100")));PlatinumStrategy platinumStrategy = new PlatinumStrategy();payContext.setStrategy(platinumStrategy);System.out.println("白银会员:"+payContext.getPrice(new BigDecimal("100")));SilverStrategy silverStrategy = new SilverStrategy();payContext.setStrategy(silverStrategy);System.out.println("白金会员:"+payContext.getPrice(new BigDecimal("100")));}
}

普通会员:100
黄金会员:80.0
白银会员:35.0
白金会员:50

优化2:策略中出现相同逻辑,如何处理

说明:策略2与策略3处理逻辑中都有需要处理的内容,这个内容可能很长,初始化参数,或者校验参数,远程调用获取数据等操作,都是类似的逻辑,可以抽取到抽象类中,子类需要哪个实现哪个方法,重复的直接在父类操作。

在这里插入图片描述

策略工厂

package com.geekmice.springbootmybatiscrud.strategy.fifth;import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/*** @author mbp* @date 2025-02-11*/
public class StrategyFactory {/*** 设置策略map*/private static Map<String, Strategy> strategyMap = new HashMap<>(16);public static Strategy getStrategyService(String type) {return strategyMap.get(type);}/*** 提前策略装入 strategyMap*/public static void register(String type, Strategy strategy) {if (Objects.isNull(type)) {return;}strategyMap.put(type, strategy);}
}

策略接口

package com.geekmice.springbootmybatiscrud.strategy.fifth;import org.springframework.beans.factory.InitializingBean;import java.math.BigDecimal;
/*** @author mbp* @date 2025-02-11*/
public interface Strategy extends InitializingBean {BigDecimal quote(BigDecimal price);}

模板方式抽象类

package com.geekmice.springbootmybatiscrud.strategy.fifth;/*** @author mbp* @date 2025-02-11*/
public abstract class BaseMember {/*** 需要父类执行关键重复逻辑*/protected void exec(){System.out.println("处理内容");}}

具体策略1

package com.geekmice.springbootmybatiscrud.strategy.fifth;import org.springframework.stereotype.Component;import java.math.BigDecimal;
/*** @author mbp* @date 2025-02-11*/
@Component
public class OrdinaryStrategy extends BaseMember  implements Strategy {@Overridepublic BigDecimal quote(BigDecimal price) {this.exec();return price;}@Overridepublic void afterPropertiesSet() throws Exception {StrategyFactory.register("1",this);}
}

具体策略2

package com.geekmice.springbootmybatiscrud.strategy.fifth;import org.springframework.stereotype.Component;import java.math.BigDecimal;
/*** @author mbp* @date 2025-02-11*/
@Component
public class GoldStrategy extends BaseMember implements Strategy {@Overridepublic BigDecimal quote(BigDecimal price) {BigDecimal res = price.multiply(new BigDecimal("0.8"));this.exec();return res;}@Overridepublic void afterPropertiesSet() throws Exception {StrategyFactory.register("2", this);}}

具体策略3

package com.geekmice.springbootmybatiscrud.strategy.fifth;import org.springframework.stereotype.Component;import java.math.BigDecimal;
/*** @author mbp* @date 2025-02-11*/
@Component
public class PlatinumStrategy extends BaseMember implements Strategy {@Overridepublic BigDecimal quote(BigDecimal price) {BigDecimal res = price.subtract(new BigDecimal("50")).multiply(new BigDecimal("0.7"));return res;}@Overridepublic void afterPropertiesSet() throws Exception {StrategyFactory.register("3", this);}
}

测试类

package com.geekmice.springbootmybatiscrud.controller;import com.geekmice.springbootmybatiscrud.dao.StudentMapper;
import com.geekmice.springbootmybatiscrud.pojo.Student;
import com.geekmice.springbootmybatiscrud.strategy.fifth.Strategy;
import com.geekmice.springbootmybatiscrud.strategy.fifth.StrategyFactory;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;/*** @author Administrator*/
@RestController
@RequestMapping("/student")
public class StudentController {@Resourceprivate StudentMapper studentMapper;@GetMapping(value = "queryAll")public List<Student> queryAll() {Strategy strategyService = StrategyFactory.getStrategyService("1");System.out.println(strategyService.quote(new BigDecimal("1000")));Strategy strategyService2 = StrategyFactory.getStrategyService("2");System.out.println(strategyService2.quote(new BigDecimal("1000")));Strategy strategyService1 = StrategyFactory.getStrategyService("3");System.out.println(strategyService1.quote(new BigDecimal("1000")));return new ArrayList<>();}}

优化3:传递策略类型

根据某个策略类型,执行某个策略逻辑

思路:需要保证某个类型对应某个策略类,通过springInitializingBean接口初始化bean,项目启动过程执行实现InitializingBean接口中的afterPropertiesSet方法,在这个方法中初始化map中指定的策略。

策略接口

public interface Strategy extends InitializingBean {BigDecimal quote(BigDecimal price);
}

策略工厂

package com.geekmice.springbootmybatiscrud.strategy.fourth;import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;
import java.util.Objects;public class StrategyFactory {/*** 设置策略map*/private static Map<String, Strategy> strategyMap = new HashMap<>(16);public static Strategy getStrategyService(String type) {return strategyMap.get(type);}/*** 提前策略装入 strategyMap*/public static void register(String type, Strategy strategy) {if (Objects.isNull(type)) {return;}strategyMap.put(type, strategy);}
}

具体策略1

package com.geekmice.springbootmybatiscrud.strategy.fourth;import com.geekmice.springbootmybatiscrud.strategy.third.PayStrategy;
import org.springframework.stereotype.Component;import java.math.BigDecimal;
@Component
public class OrdinaryStrategy implements Strategy {@Overridepublic BigDecimal quote(BigDecimal price) {
//        System.out.println("都要处理的内容");return price;}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("11111111111");StrategyFactory.register("1",this);}
}

具体策略2

package com.geekmice.springbootmybatiscrud.strategy.fourth;import com.geekmice.springbootmybatiscrud.strategy.third.PayStrategy;
import org.springframework.stereotype.Component;import java.math.BigDecimal;
@Component
public class GoldStrategy implements Strategy {@Overridepublic BigDecimal quote(BigDecimal price) {BigDecimal res = price.multiply(new BigDecimal("0.8"));return res;}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("222222222222");StrategyFactory.register("2",this);}
}

具体策略3

package com.geekmice.springbootmybatiscrud.strategy.fourth;import com.geekmice.springbootmybatiscrud.strategy.third.PayStrategy;
import org.springframework.stereotype.Component;import java.math.BigDecimal;
@Component
public class PlatinumStrategy implements Strategy {@Overridepublic BigDecimal quote(BigDecimal price) {// 都要处理的内容// System.out.println("都要处理的内容");BigDecimal res = price.subtract(new BigDecimal("50")).multiply(new BigDecimal("0.7"));return res;}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("3333333333333");StrategyFactory.register("3",this);}}

测试

package com.geekmice.springbootmybatiscrud.controller;import com.geekmice.springbootmybatiscrud.dao.StudentMapper;
import com.geekmice.springbootmybatiscrud.pojo.Student;
import com.geekmice.springbootmybatiscrud.strategy.first.StrategyFactory;
import com.geekmice.springbootmybatiscrud.strategy.fourth.Strategy;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;/*** @author Administrator*/
@RestController
@RequestMapping("/student")
public class StudentController {@Resourceprivate StudentMapper studentMapper;@GetMapping(value = "queryAll")public List<Student> queryAll() {Strategy strategyService =StrategyFactory.getStrategyService("1");System.out.println(strategyService);System.out.println(strategyService.quote(new BigDecimal("1000")));return new ArrayList<>();}}

http://www.ppmy.cn/news/1571626.html

相关文章

二、数据持久化篇(深度增强版)

二、数据持久化篇&#xff08;深度增强版&#xff09; 2.1 JDBC Template深度解析 架构设计思想 #mermaid-svg-y2IrKiVu2gzenoCB {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-y2IrKiVu2gzenoCB .error-icon{fil…

DeepSeek遇袭后的深思:ManageEngine ITOM如何筑牢安全防线

在科技飞速发展的当下&#xff0c;大模型领域正以前所未有的速度改变着我们的生活和工作方式。DeepSeek作为大模型赛道上的重要参与者为众多行业带来了新的机遇和变革。然而&#xff0c;近期DeepSeek遭受网络攻击的事件&#xff0c;却如同一记警钟&#xff0c;在整个行业内回荡…

Django学习笔记(第一天:Django基本知识简介与启动)

博主毕业已经工作一年多了&#xff0c;最基本的测试工作已经完全掌握。一方面为了解决当前公司没有自动化测试平台的痛点&#xff0c;另一方面为了向更高级的测试架构师转型&#xff0c;于是重温Django的知识&#xff0c;用于后期搭建测试自动化平台。 为什么不选择Java&#x…

WRF-Hydro:高级水文建模系统详解

1. WRF-Hydro 概述 什么是 WRF-Hydro&#xff1f; WRF-Hydro&#xff08;Weather Research and Forecasting Hydrological modeling system&#xff09;是由美国国家大气研究中心&#xff08;NCAR&#xff09;开发的一个用于耦合气象模型和水文模型的高级建模系统。它旨在提供…

一竞技瓦拉几亚S4预选:YB 2-0击败GG

在2月11号进行的PGL瓦拉几亚S4西欧区预选赛上,留在欧洲训练的YB战队以2-0击败GG战队晋级下一轮。双方对阵第二局:对线期YB就打出了优势,中期依靠卡尔带队进攻不断扩大经济优势,最终轻松碾压拿下比赛胜利,以下是对决战报。 YB战队在天辉。阵容是潮汐、卡尔、沙王、隐刺、发条。G…

探索 API 文档新境界:Swagger 助力生成带权限控制的 API 文档

各位开发者朋友们&#xff01;在咱们的开发工作里&#xff0c;API 文档就像是项目的说明书&#xff0c;清晰准确的文档能让我们的开发效率大幅提升。而当涉及到权限控制时&#xff0c;如何生成既安全又详细的 API 文档就成了一个关键问题。今天&#xff0c;我就和大家好好唠唠如…

React进行路由跳转的方法汇总

在 React 中进行路由跳转有多种方法&#xff0c;具体取决于你使用的路由库和版本。以下是常见的路由跳转方法汇总&#xff0c;主要基于 react-router-dom 库。 1. 使用 useNavigate 钩子&#xff08;适用于 react-router-dom v6&#xff09; useNavigate 是 react-router-dom…

Android图片加载框架Coil,Kotlin

Android图片加载框架Coil&#xff0c;Kotlin implementation("io.coil-kt:coil:1.4.0") import android.os.Bundle import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import coil.Coil i…