当前位置:首页 » 《随便一记》 » 正文

策略模式详解

21 人参与  2024年12月09日 18:01  分类 : 《随便一记》  评论

点击全文阅读


汇总目录请点击访问:《设计模式目录汇总》
喜欢内容的话欢迎关注、点赞、收藏!感谢支持,祝大家祉猷并茂,顺遂无虞

策略模式(Strategy Pattern)详解

定义

策略模式是一种行为型设计模式,它允许你在运行时选择算法或行为,而不是在编译时确定。通过将具体算法封装成独立的类,并通过一个统一的接口与客户端交互,可以实现算法的动态替换,同时避免了代码的重复和复杂条件语句。

通俗地说,策略模式就像换工具干活:你有一堆工具(算法),可以根据任务需要随时选择最合适的那个,而不用修改已有工具或任务逻辑。


生活中的例子

支付方式
当你购物结算时,可以选择支付宝、微信支付、信用卡等不同方式。这些支付方式是不同的“策略”,系统根据用户选择动态调用对应策略。

导航应用
地图导航中可以选择不同的路径规划方式,如“最短时间”、“最短距离”或“避开拥堵”。每种规划方式对应一个策略。

促销活动
商场在不同节日可能有“满减”、“折扣”或“积分兑换”等促销方案,策略模式可以轻松切换不同的促销方案。


策略模式的特点

优点

简化代码:避免复杂的条件语句(如 if-elseswitch)。易于扩展:新增算法时,只需增加一个策略类,不影响其他代码。行为动态化:可以在运行时更换策略,提升程序灵活性。

缺点

类数增加:每个策略都需要一个类,可能导致类数量激增。客户端需要了解不同策略:客户端需要知道何时选择哪个策略。

适用场景

场景

示例

行为变化需要动态选择

支付方式切换、算法选择

减少条件语句的复杂性

替代复杂的 if-elseswitch 语句

需要扩展算法或行为

新增促销活动、增加新的导航规划方式


策略模式的实现步骤

定义策略接口
所有策略(算法)共有的接口,规定统一的方法签名。

实现具体策略
每个策略(算法)实现该接口,封装具体的行为。

定义上下文类(Context)
上下文持有策略的引用,负责调用策略对象的算法,而无需关心策略的具体实现。

客户端动态设置策略
客户端通过上下文动态选择需要使用的策略。


策略模式与其他模式的对比

特性策略模式工厂方法模式
核心关注点动态切换算法或行为,将算法封装成对象,使得算法可以相互替换。动态创建对象,将对象的创建和使用分离,使得系统更容易扩展。
行为扩展方式添加新的策略实现类,不需要修改原有代码,只需添加新的策略类即可扩展新的行为。添加新的工厂或子类,不需要修改原有工厂代码,只需添加新的工厂类即可创建新的对象。
客户端角色客户端需要了解并选择策略,以便在运行时根据需要选择和切换不同的策略。客户端通常只需调用工厂方法来获取所需的对象,不关心对象是如何被创建和表示的。

C++ 示例:支付方式选择

#include <iostream>#include <memory>#include <string>using namespace std;// 策略接口class PaymentStrategy {public:    virtual void pay(int amount) = 0;    virtual ~PaymentStrategy() = default;};// 具体策略:支付宝支付class Alipay : public PaymentStrategy {public:    void pay(int amount) override {        cout << "Paid " << amount << " using Alipay." << endl;    }};// 具体策略:信用卡支付class CreditCard : public PaymentStrategy {public:    void pay(int amount) override {        cout << "Paid " << amount << " using Credit Card." << endl;    }};// 上下文类class PaymentContext {private:    unique_ptr<PaymentStrategy> strategy;public:    void setStrategy(unique_ptr<PaymentStrategy> newStrategy) {        strategy = move(newStrategy);    }    void executePayment(int amount) {        if (strategy) {            strategy->pay(amount);        } else {            cout << "No payment strategy set!" << endl;        }    }};// 客户端代码int main() {    PaymentContext context;    // 使用支付宝支付    context.setStrategy(make_unique<Alipay>());    context.executePayment(100);    // 切换到信用卡支付    context.setStrategy(make_unique<CreditCard>());    context.executePayment(200);    return 0;}

C# 示例:导航规划

using System;// 策略接口public interface IRouteStrategy {    void BuildRoute(string start, string end);}// 具体策略:最短时间路径public class FastestRoute : IRouteStrategy {    public void BuildRoute(string start, string end) {        Console.WriteLine($"Building the fastest route from {start} to {end}.");    }}// 具体策略:最短距离路径public class ShortestRoute : IRouteStrategy {    public void BuildRoute(string start, string end) {        Console.WriteLine($"Building the shortest route from {start} to {end}.");    }}// 上下文类public class Navigator {    private IRouteStrategy _strategy;    public void SetStrategy(IRouteStrategy strategy) {        _strategy = strategy;    }    public void BuildRoute(string start, string end) {        if (_strategy != null) {            _strategy.BuildRoute(start, end);        } else {            Console.WriteLine("No route strategy set!");        }    }}// 客户端代码class Program {    static void Main(string[] args) {        var navigator = new Navigator();        // 使用最短时间路径        navigator.SetStrategy(new FastestRoute());        navigator.BuildRoute("Home", "Office");        // 切换到最短距离路径        navigator.SetStrategy(new ShortestRoute());        navigator.BuildRoute("Home", "Gym");    }}

策略模式的类图


策略模式总结

灵活性高:可以轻松地添加新策略,扩展性好。职责清晰:将算法逻辑封装在独立的策略类中,简化了上下文的代码。场景适配:非常适合需要动态切换行为或算法的场景,比如支付系统、导航系统等。注意点:避免类爆炸(策略类过多),并且客户端需要了解可用策略的功能。

欢迎关注、点赞、收藏!更多系列内容可以点击专栏目录订阅,感谢支持,再次祝大家祉猷并茂,顺遂无虞
在这里插入图片描述

若将文章用作它处,请一定注明出处,商用请私信联系我!


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/198756.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1