【设计模式】策略模式(政策(Policy)模式)

发布于:2025-07-14 ⋅ 阅读:(15) ⋅ 点赞:(0)

策略模式(Strategy Pattern)详解


一、策略模式简介

策略模式(Strategy Pattern) 是一种 行为型设计模式(对象行为型模式),它定义了一系列算法,并将每一个算法封装起来,使它们可以互相替换,独立于使用它们的客户端。

又称为政策(Policy)模式
每一个封装算法的类称之为策略(Strategy)类
策略模式提供了一种可插入式(Pluggable)算法的实现方案。

你可以把它理解为:

“一个工具箱里有多个工具,你可以在不同场景下选择不同的工具来完成任务。”

在策略模式中,这些“工具”就是各种具体的策略类,而“任务执行者”则是使用这些策略的对象。

旅游出行方式
在这里插入图片描述
实现某个目标的途径不止一条,可根据实际情况选择一条合适的途径。

软件开发
多种算法,例如排序、查找、打折等
使用硬编码(Hard Coding)实现将导致系统违背开闭原则,扩展性差,且维护困难
可以定义一些独立的类来封装不同的算法,每一个类封装一种具体的算法 —> 策略类

public class Context
{
    ……
    public void algorithm(String type)  
    {
        ......
        if(type == "strategyA")
        {
            //算法A
        }
        else if(type == "strategyB")
        {
            //算法B
        }
        else if(type == "strategyC")
        {
            //算法C
        }
        ......
    }
    ……
} 

策略模式包含以下3个角色
Context(环境类)
Strategy(抽象策略类)
ConcreteStrategy(具体策略类)

在这里插入图片描述


二、解决的问题类型

策略模式主要用于解决以下问题:

  • 同一行为具有多种实现方式:比如支付方式可以是支付宝、微信、银行卡等。
  • 避免大量的 if-else 或 switch-case 判断逻辑:提高代码可读性和扩展性。
  • 希望在运行时动态切换算法或行为:比如根据用户等级选择不同的折扣策略。

三、使用场景

场景 示例
不同支付方式 支付宝、微信、银联等
折扣计算 普通会员、VIP会员、超级会员等不同折扣规则
物流配送 顺丰、京东、德邦等不同物流策略
游戏角色技能 角色攻击方式随武器变化而变化

四、核心结构

策略模式通常包含三个部分:

  1. 策略接口(Strategy):定义所有策略共有的行为。
  2. 具体策略类(Concrete Strategies):实现接口中的具体行为。
  3. 上下文类(Context):持有一个策略接口的引用,负责调用策略方法。

五、实际代码案例(Java)

我们以电商系统中的“支付方式”为例,演示策略模式的使用。

1. 定义策略接口

// 支付策略接口
public interface PaymentStrategy {
    void pay(int amount);
}

2. 实现具体策略类

// 微信支付策略
public class WeChatPay implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("WeChat Pay: $" + amount);
    }
}

// 支付宝支付策略
public class AliPay implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("AliPay: $" + amount);
    }
}

// 银行卡支付策略
public class BankCardPay implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("Bank Card Pay: $" + amount);
    }
}

3. 创建上下文类

// 上下文类:支付环境
public class ShoppingCart {
    private PaymentStrategy paymentStrategy;

    // 设置策略
    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }

    // 使用策略进行支付
    public void checkout(int amount) {
        if (paymentStrategy == null) {
            throw new IllegalStateException("Please select a payment strategy.");
        }
        paymentStrategy.pay(amount);
    }
}

4. 客户端测试类

public class Client {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        // 使用微信支付
        cart.setPaymentStrategy(new WeChatPay());
        cart.checkout(100);

        // 切换为支付宝支付
        cart.setPaymentStrategy(new AliPay());
        cart.checkout(200);

        // 切换为银行卡支付
        cart.setPaymentStrategy(new BankCardPay());
        cart.checkout(300);
    }
}

输出结果:

WeChat Pay: $100
AliPay: $200
Bank Card Pay: $300

典型代码(C++)

典型的抽象策略类代码

abstract class AbstractStrategy
{
    public abstract void Algorithm(); //声明抽象算法
}

典型的抽象策略类代码

class ConcreteStrategyA : AbstractStrategy 
{
//算法的具体实现
public override void Algorithm() 
{
    //算法A
}
}

典型的环境类代码

class Context
{
	private AbstractStrategy strategy; //维持一个对抽象策略类的引用
	public void SetStrategy(AbstractStrategy strategy) 
	{
	    this.strategy = strategy;
	}
	//调用策略类中的算法
	public void Algorithm() 
	{
	    strategy.Algorithm();
	}
}

典型的客户端代码片段

……
Context context = new Context();
AbstractStrategy strategy;
strategy = new ConcreteStrategyA(); //可在运行时指定类型,通过配置文件和反射机制实现
context.SetStrategy(strategy);
context.Algorithm();
……
其他案例
  1. 某软件公司为某电影院开发了一套影院售票系统,在该系统中需要为不同类型的用户提供不同的电影票打折方式,具体打折方案如下:
    (1) 学生凭学生证可享受票价8折优惠。
    (2) 年龄在10周岁及以下的儿童可享受每张票减免10元的优惠(原始票价需大于等于20元)。
    (3) 影院VIP用户除享受票价半价优惠外还可进行积分,积分累计到一定额度可换取电影院赠送的奖品。
    该系统在将来可能还要根据需要引入新的打折方式。现使用策略模式设计该影院售票系统的打折方案

在这里插入图片描述

  1. 排序策略
    某系统提供了一个用于对数组数据进行操作的类,该类封装了对数组的常见操作,如查找数组元素、对数组元素进行排序等。现以排序操作为例,使用策略模式设计该数组操作类,使得客户端可以动态地更换排序算法,可以根据需要选择冒泡排序或选择排序或插入排序,也能够灵活地增加新的排序算法。

在这里插入图片描述

  1. 旅游出行策略
    旅游出行方式可以有多种,如可以乘坐飞机旅游,也可以乘火车旅游,如果有兴趣自行车游也是一种极具乐趣的出行方式。不同的旅游出行方式有不同的实现过程,客户根据自己的需要选择一种合适的旅游方式。在本实例中我们用策略模式来模拟这一过程。

在这里插入图片描述

六、优缺点分析

优点 描述
解耦 将算法和使用它的对象分离,降低耦合度
易于扩展 新增策略只需新增类,符合开闭原则。提供了对开闭原则的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为
运行时可切换策略 提供更高的灵活性
减少冗长的条件判断语句 替代 if-else 或 switch-case 结构
其他 提供了管理相关的算法族的办法,提供了一种可以替换继承关系的办法,提供了一种算法的复用机制,不同的环境类可以方便地复用策略类
缺点 描述
增加类数量 每个策略对应一个类,可能导致类膨胀,将造成系统产生很多具体策略类
需要对外暴露策略类 客户端需了解所有策略才能选择使用哪个
不适合简单分支逻辑 如果策略种类很少,使用策略模式反而增加了复杂度
其他 无法同时在客户端使用多个策略类

七、与其他模式对比(补充)

模式名称 目标
模板方法模式 在父类定义算法骨架,子类实现具体步骤
责任链模式 请求在链上传递,每个节点决定是否处理请求
策略模式 多种算法/行为封装成策略,运行时可切换

八、最终小结

策略模式是一种非常实用的设计模式,适用于那些具有多种实现方式、需要灵活切换的业务逻辑。它通过将行为抽象为接口和实现类,使得程序更加清晰、易维护、易扩展。

在开发电商系统、支付模块、权限控制、游戏逻辑等项目中,策略模式都能发挥重要作用。


📌 一句话总结:

策略模式就像“万能遥控器”,可以自由切换不同的功能模块,让程序更灵活、更具适应性。


推荐使用方式:

  • 对于固定的行为,但实现方式多样的场景优先考虑策略模式;
  • 可结合工厂模式统一创建策略实例,提升管理效率;
  • 使用 Lambda 表达式简化简单策略的实现(如 Java 8+);

部分内容由AI大模型生成,注意识别!


网站公告

今日签到

点亮在社区的每一天
去签到