做网站哪个平台好,上海外企公司有哪些,免费网站空间怎么办,北京企业网站建站哪家好这是【Dart 教程系列第 49 篇】#xff0c;如果觉得有用的话#xff0c;欢迎关注专栏。
博文当前所用 Flutter SDK#xff1a;3.22.1、Dart SDK#xff1a;3.4.1 文章目录 一#xff1a;什么是策略设计模式#xff1f;二#xff1a;为什么要使用策略设计模式#xff1…这是【Dart 教程系列第 49 篇】如果觉得有用的话欢迎关注专栏。
博文当前所用 Flutter SDK3.22.1、Dart SDK3.4.1 文章目录 一什么是策略设计模式二为什么要使用策略设计模式举例说明三如何使用策略设计模式举例说明3-1定义抽象策略角色 Strategy3-2实现具体的策略角色 Concrete Strategy 3-3创建环境角色 Context3-4创建特定策略对象并将其传递给环境角色 Context 四策略模式的优缺点五策略模式的其它应用 一什么是策略设计模式
策略设计模式是行为型设计模式之一它在 Gof Book 书中的描述如下 在计算机编程中策略模式是一种行为软件设计模式允许在运行时选择算法。代码不是直接实现单个算法而是接收运行时指令决定使用哪一组算法。 标准策略模式的 UML 如下图所示 由上图可以看出
Strategy策略- 也可以叫抽象策略角色用以声明一个支持所有算法的接口并通过 Context 来执行特定策略的方法Concrete Strategy具体策略- 也可以叫具体策略角色使用 Strategy 接口实现不同的算法。Context 只是使用这个接口并不关心算法的具体实现Context上下文- 也可以叫环境角色保存对 Strategy 对象的引用但不依赖于算法的实现方式。
最后由客户端创建一个特定的策略对象并将其传递给 Context 即可。
二为什么要使用策略设计模式举例说明
策略模式允许在运行时选择算法或行为将算法的使用和实现分离提高系统的灵活性和可扩展性。
举例说明
在举例策略模式之前我们先来看一下同样的需求如果不使用策略模式而是使用一般的 if…else 条件语句来处理会有什么问题。
某视频剪辑类 APP 提供了不同的工具如链接转文字、视频转文字、智能配音和去水印等功能APP 刚上线为吸引更多的用户所以允许用户免费使用这些工具。因为目前只有一种免费的支付方式此时后端定义的获取订单号接口只需要传入工具的 id 就可以了所以你的代码可能是这样写的。
... tag1
/// 支付状态
Futurebool payStatus(int toolId) async {// 创建工具订单号final String orderNo await getToolsOrder(toolId: toolId);// 根据订单号后等待工具处理的结果final bool res await doSomething(orderNo);return res;
}后来用户量上来了APP 内对使用工具做了以下调整。将原先的免费使用工具更改为每天可免费使用某工具一定的次数免费次数用完后再使用工具需要通过观看广告后才可以。现在的支付方式增加到了两种为此你定义了一个支付类型的枚举
/// 支付类型
enum PayOrderType {free, // 免费ad, // 看广告
}后端提供的获取订单号接口也增加了一个支付类型的入参只针对免费支付类型而言此时 tag1 代码需要做如下调整
... tag2
Futurebool payStatus(int toolId, PayOrderType payOrderType) async {if (payOrderType PayOrderType.free) {final String orderNo await getToolsOrder(toolId: toolId, payOrderType: PayOrderType.free);final bool res await doSomething(orderNo);return res;}... 暂时省略部分代码return false;
}可以对比下 tag1 和 tag2 的代码修改了哪里不知道你发现什么问题了没如果没有也没关系我们继续往下看。
如果是看广告类型的支付方式调用第三方广告 SDK 时要求需要传入广告位的标识 key为此 tag2 的代码不得不再增加一个入参 positionKey并增加调用观看广告的方法以及是否观看完的判断如下代码所示。
... tag3
Futurebool payStatus(int toolId, PayOrderType payOrderType, String positionKey) async {if (payOrderType PayOrderType.free) {final String orderNo await getToolsOrder(toolId: toolId, payOrderType: PayOrderType.free);final bool res await doSomething(orderNo);return res;}else if (payOrderType PayOrderType.ad) {final String orderNo await getToolsOrder(toolId: toolId, payOrderType: PayOrderType.ad);// 看广告final ADResult adRes await openRewardAD(positionKey);if (adRes.code ! 1) {return false;}final bool res await doSomething(orderNo);return res;}return false;
}这样写也能实现需求但不知道你发现一个问题没随着支付方式的增加payStatus 方法就会不断的根据实际情况增加入参并实现相关支付方式的代码且不断的增加新的 else if 判断这违背了六大设计原则之一的 OCPOpen Close Principle开放封闭原则也就是对扩展开放但对修改关闭。
我们应该需要这么一种设计理念当后面再增加新的需求时应该是在不变动当前正常运行的代码下通过其他方式新增代码实现新需求。如果为了新需求而改动原有代码可能会造成其他调用原本代码的地方发生预期之外的错误。
此时我们的主角策略模式终于要闪亮登场了。
三如何使用策略设计模式举例说明
基于目录二的需求我们通过观察发现无论是哪种支付方式我们都是先根据传入的工具 id 创建订单号然后在工具处理完成后返回结果所以可以把这个行为抽象出来一个接口也就是使用策略模式的第一步。
3-1定义抽象策略角色 Strategy
/// 策略公共接口
abstract class IPayStrategy {Futurebool payStatus(int toolId);
}3-2实现具体的策略角色 Concrete Strategy
对于目录二的免费支付方式而言具体的实现如下代码所示
/// 免费支付策略
final class PayStrategyByFree implements IPayStrategy {overrideFuturebool payStatus(int toolId) async {final String orderNo await getToolsOrder(toolId: toolId, payOrderType: PayOrderType.free);final bool res await doSomething(orderNo);return res;}
}对于目录二的看广告支付方式而言具体的实现如下代码所示
/// 看广告支付策略
final class PayStrategyByAD implements IPayStrategy {final String positionKey; // 广告位标识 keyPayStrategyByAD(this.positionKey);overrideFuturebool payStatus(int toolId) async {final String orderNo await getToolsOrder(toolId: toolId, payOrderType: PayOrderType.ad);// 看广告final ADResult adRes await openRewardAD(positionKey);if (adRes.code ! 1) {return false;}final bool res await doSomething(orderNo);return res;}
}可以看出看广告时所需的广告位标识 key由支付策略类的构造函数传入。
3-3创建环境角色 Context
抽象策略和具体策略都已实现现在创建环境角色 Context其持有对抽象策略的引用并决定使用哪种策略。
/// 支付上下文持有一个策略对象的引用
class PayContext {final IPayStrategy iPayStrategy;PayContext({required this.iPayStrategy});Futurebool getPayStatus(int toolId) async {return iPayStrategy.payStatus(toolId);}
}3-4创建特定策略对象并将其传递给环境角色 Context
一切的铺垫都已完成光说不练假把式现在就让我们把策略模式应用在支付方式上吧。
// 工具是否免费
bool isFree false;
// 支付策略
late IPayStrategy strategy;
// 免费的支付策略
if (isFree) {strategy PayStrategyByFree();
}
// 看广告的支付策略
else {strategy PayStrategyByAD();
}
// 支付状态传入具体的支付策略
final bool success await PayContext(iPayStrategy: strategy).getPayStatus(123456);
// ... 根据支付状态处理后续业务这里首先根据条件创建了不同的策略对象然后把策略对象传递给了环境角色 Context由环境角色 Context 负责调用具体的策略方法。后面如果再增加其他的支付方式的话只需要再声明一个策略类并实现具体的算法即可。相比较使用 if…else 的条件语句来说对外提供了扩展对内又限制修改符合 OCP 原则。
至此关于什么是策略模式以及如何使用策略模式便介绍到这里了。
四策略模式的优缺点
没有最好的设计模式只用相对合适的设计模式。策略模式的优缺点如下
优点
算法可以自由切换避免使用了多重条件判断扩展性良好
缺点
策略类会逐渐增多所有策略类都需要对外暴露
五策略模式的其它应用
除了本文举例的支付方式可以使用策略模式外符合策略模式定义和使用场景的都可以使用该模式。如
支付选项策略。如支付类型是使用微信、支付宝、信用卡还是银行转账等支付类型。游戏伤害计算。如使用不同的招式技能为不同的攻击定义不同的算法。排序算法。如把不同的算法冒泡排序、快排排序、选择排序等通过不同的策略类实现最终调用公共的 Sort 接口。电商平台优惠卷系统。如不同的优惠卷有不同的使用策略例如满减、打折、买赠等方式。…
还有很多其它案例就不一一说明了知道什么时候该用策略模式以及如何使用策略模式即可以不变应万变。
你的问题得到解决了吗欢迎在评论区留言。
赠人玫瑰手有余香如果觉得文章不错希望可以给个一键三连感谢。 结束语 技术是一点一点积累的大神也不是一天就可以达到的。原地不动就是退步所以每天进步一点点。 最后附上一句格言好学若饥谦卑若愚望共勉。