《设计模式》策略模式

1.策略模式定义

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一组算法,将每个算法封装起来,并使它们可以相互替换,从而让算法的变化独立于使用它的客户(Client)。

换句话说, 策略模式让一个类的行为或其算法可以在运行时更改,而不会影响使用该类的代码。

UML图:

在这里插入图片描述

2.策略模式举例:

业务场景:需要实现一个商场收银系统,有三种策略,

  1. 正常结账
  2. 打折
  3. 满减
    实现业务功能如下:

2.1 代码设计UML图如下:

在这里插入图片描述

2.2 关键代码:

CashContext代码:和抽象工厂结合,减少耦合。之前客户端需要了解CashContext和CashSuper两个类,现在只需要了解CashContext一个类,封装更好,耦合更小。

public class CashContext {

    private CashSuper cs;   //声明一个CashSuper对象

    //通过构造方法,传入具体的收费策略
    public CashContext(int cashType){
        switch(cashType){
            case 1:
                this.cs = new CashNormal();
                break;
            case 2:
                this.cs = new CashRebate(0.8d);
                break;
            case 3:
                this.cs = new CashRebate(0.7d);
                break;
            case 4:
                this.cs = new CashReturn(300d,100d);
                break;
        }
    }

    public double getResult(double price,int num){
        //根据收费策略的不同,获得计算结果
        return this.cs.acceptCash(price,num);
    }    
}

CashSuper:


public abstract class CashSuper {
    public abstract double acceptCash(double price,int num);
}

CashReturn:

public class CashReturn extends CashSuper {

    private double moneyCondition = 0d; //返利条件
    private double moneyReturn = 0d;    //返利值

    //返利收费。初始化时需要输入返利条件和返利值。
    //比如“满300返100”,就是moneyCondition=300,moneyReturn=100
    public CashReturn(double moneyCondition,double moneyReturn){
        this.moneyCondition = moneyCondition;
        this.moneyReturn = moneyReturn;
    }

    //计算收费时,当达到返利条件,就原价减去返利值
    public double acceptCash(double price,int num){
        double result = price * num;
        if (moneyCondition>0 && result >= moneyCondition)
            result = result - Math.floor(result / moneyCondition) * moneyReturn; 
        return result;
    }
    
}

客户端代码:

public class Test {

	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("策略模式和简单工厂模式");
		System.out.println();		

		int discount = 0; 		//商品折扣模式(1.正常收费 2.打八折 3.打七折)
		
		double price = 0d; 		//商品单价
		int num = 0;			//商品购买数量
		double totalPrices = 0d;//当前商品合计费用
		double total = 0d;		//总计所有商品费用
	
		Scanner sc = new Scanner(System.in);

		do {
			System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折 4.满300送100):");	
			discount = Integer.parseInt(sc.nextLine());
			System.out.println("请输入商品单价:");	
			price = Double.parseDouble(sc.nextLine());
			System.out.println("请输入商品数量:");	
			num = Integer.parseInt(sc.nextLine());
			System.out.println();	

			if (price>0 && num>0){
				//根据用户输入,将对应的策略对象作为参数传入CashContext对象中
				CashContext cc = new CashContext(discount);
				
				//通过Context的getResult方法的调用,可以得到收取费用的结果
				//让具体算法与客户进行了隔离
				totalPrices = cc.getResult(price,num);
				
				total = total + totalPrices;
				
				System.out.println();	
				System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");	
				System.out.println();
				System.out.println("总计:"+ total+"元");	
				System.out.println();
			}
		}while(price>0 && num>0);

		System.out.println();
		System.out.println("**********************************************");

	}
}

具体运行结果如下:
在这里插入图片描述

3.策略模式优缺点

✅ 优点

  • 符合开闭原则(Open-Closed Principle):可以新增新的策略,而不影响已有代码。
  • 避免冗长的 if-else 语句:如果不使用策略模式,可能会有大量 if-else 逻辑判断。
  • 支持动态切换:可以在运行时自由更换不同的算法,而不修改原有代码。
  • 代码更符合SOLID原则
设计原则策略模式如何符合
单一职责原则(SRP)每个 Strategy 只负责一个算法,职责清晰。
开闭原则(OCP)可以新增策略,而不修改原代码。
依赖倒置原则(DIP)Context 依赖于 Strategy 接口,而不是具体实现。

❌ 缺点

  • 增加了代码复杂度:每个策略都需要定义一个类,当策略过多时,会导致类爆炸。
  • 客户端需要了解不同策略:调用方需要知道有哪些可用策略,才能正确选择。

4.策略模式的应用场景

✅ (1) 算法的可替换性

计算税收(不同国家税率)
支付方式(微信支付、支付宝、银行卡)

✅ (2) 处理不同格式的文件

解析 JSON、XML、CSV 文件时,使用不同的解析策略。

✅ (3) AI/机器学习中的优化策略

训练模型时,可以使用不同的优化算法(SGD、Adam、RMSprop)。

5.策略模式 vs 其他模式

设计模式作用适用场景
策略模式允许在运行时更换不同算法当有多种算法可选,且希望避免 if-else 逻辑。
状态模式允许对象在不同状态下表现出不同行为对象的行为依赖于状态变化,例如订单状态。
工厂模式负责创建对象,但不指定其具体实现需要动态创建不同策略对象时,可结合策略模式使用。

6.总结

策略模式核心思想: 定义一组算法,让它们可以互相替换,而不会影响客户端代码。
适用于: 需要多个可替换算法,并希望避免 if-else 逻辑的场景。
优点: 符合开闭原则,可动态切换策略,避免冗长 if-else
缺点: 可能会增加类的数量,使代码更复杂。

7.参考引用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值