当前位置: 首页 > news >正文

【软考设计模式】策略模式:算法族的封装与动态切换精讲

系列定位:软考软件设计师 / 系统架构设计师 — 行为型模式专题第 1 讲

考察分值:上午题 1-2 分,下午题常作为代码填空或类图识别出现

难度等级:⭐⭐⭐☆☆(结构清晰,Context 与 Strategy 的组合关系是填空重点)


一、考纲定位与模式定义

1.1 考纲要求

策略模式在软考中属于行为型模式的基础内容。考察形式包括:

  • 上午选择题:判断场景描述所属模式;识别策略模式与状态模式、模板方法模式的区别;判断 Context 与 Strategy 的关系(组合 vs 继承)

  • 下午设计题:补全 Context 类中setStrategy()execute()方法的代码;补全 ConcreteStrategy 中算法实现的代码;识别类图中 Context、Strategy、ConcreteStrategy 三个角色

1.2 模式定义

策略模式:定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。

核心意图:当一个系统需要多种算法/策略来完成同一件事(如不同的促销方式、不同的支付方式、不同的排序算法),且这些算法需要动态切换时,如果将所有算法写在一个类里用if-elseswitch判断,会导致类臃肿、难以扩展。策略模式将每种算法封装为独立的策略类,Context 通过组合持有策略对象,运行时动态替换,让算法的变化独立于使用算法的客户。

通俗理解

你去旅游,从 A 地到 B 地有多种策略:坐飞机(快但贵)、坐高铁(中等)、自驾(自由但累)。"去旅游" 这件事是 Context,"交通方式" 是 Strategy。你不需要在出门前就把所有交通方式的细节都写在行程单里(if-else),而是到了车站根据情况动态选择一种策略(买票/租车)。如果未来新增了 "骑共享单车" 这种方式,只需新增一个策略类,不需要修改行程单(Context)的代码。


二、UML 类图与角色划分

┌─────────────────────────────────────────────────────────┐ │ Client │ │ + main() │ │ ├── Context ctx = new Context(); │ │ ├── ctx.setStrategy(new ConcreteStrategyA()); │ │ └── ctx.execute(); // 实际执行的是策略 A 的算法 │ └───────────────────────┬─────────────────────────────────┘ │ uses ▼ ┌─────────────────────────────────────────────────────────┐ │ Context │ │ ── 上下文:持有策略引用,调用策略的算法 ── │ │ - strategy: Strategy ◄── 组合关系 │ │ + setStrategy(Strategy s) { │ │ this.strategy = s; │ │ } │ │ + execute() { │ │ strategy.algorithm(); // 委托给策略执行 │ │ } │ └───────────────────────┬─────────────────────────────────┘ │ delegates to ▼ ┌─────────────────────────────────────────────────────────┐ │ <<interface>> │ │ Strategy │ │ + algorithm() │ └───────────────────────┬─────────────────────────────────┘ ┌────────────┴────────────┐ ▼ ▼ ┌─────────────────────┐ ┌─────────────────────┐ │ ConcreteStrategyA │ │ ConcreteStrategyB │ │ + algorithm() { │ │ + algorithm() { │ │ // 算法 A 实现 │ │ // 算法 B 实现 │ │ } │ │ } │ └─────────────────────┘ └─────────────────────┘
角色职责软考填空关键词
Context(上下文)持有一个 Strategy 的引用,定义一个接口让客户端可以设置/更换策略,将操作委托给策略对象执行class+private Strategy strategy+setStrategy()+execute()
Strategy(抽象策略)定义所有支持的算法的公共接口,让 Context 可以统一调用interface/abstract class+algorithm()
ConcreteStrategy(具体策略)实现 Strategy 接口,封装具体的算法或行为implements Strategy+ 具体算法实现
Client(客户端)创建 Context 和 ConcreteStrategy,通过setStrategy()将策略注入 Context,调用execute()new Context()+context.setStrategy(new XxxStrategy())

类图识别要点:软考类图中,策略模式的核心特征是Context 类通过组合(聚合)持有一个 Strategy 引用(带空心菱形的实线),且 Context 中有setStrategy()方法用于动态更换策略。如果类图里有一个类持有另一个接口的引用,且有 setter 方法可以替换 → 策略模式。


三、场景一:电商促销策略(最经典的策略模式)

业务背景:电商系统需要支持多种促销策略:满减(满 100 减 20)、折扣(打 8 折)、直降(立减 15 元)。结算时根据用户选择的优惠券类型,动态应用不同的计价策略。要求新增促销方式时不需要修改结算核心代码。

说明:这是策略模式最经典的例子,也是软考下午题最爱考的 "多种算法动态切换" 场景。

3.1 代码实现
// Strategy:促销策略接口 public interface PromotionStrategy { double calculatePrice(double originalPrice); } // ConcreteStrategy:满减策略 public class FullReductionStrategy implements PromotionStrategy { private double threshold; private double reduction; public FullReductionStrategy(double threshold, double reduction) { this.threshold = threshold; this.reduction = reduction; } @Override public double calculatePrice(double originalPrice) { if (originalPrice >= threshold) { return originalPrice - reduction; } return originalPrice; } } // ConcreteStrategy:折扣策略 public class DiscountStrategy implements PromotionStrategy { private double discountRate; public DiscountStrategy(double discountRate) { this.discountRate = discountRate; } @Override public double calculatePrice(double originalPrice) { return originalPrice * discountRate; } } // ConcreteStrategy:直降策略 public class DirectReductionStrategy implements PromotionStrategy { private double reduction; public DirectReductionStrategy(double reduction) { this.reduction = reduction; } @Override public double calculatePrice(double originalPrice) { double finalPrice = originalPrice - reduction; return finalPrice > 0 ? finalPrice : 0; } } // Context:结算上下文 public class CheckoutContext { private PromotionStrategy strategy; public void setStrategy(PromotionStrategy strategy) { this.strategy = strategy; } public double executeCheckout(double originalPrice) { if (strategy == null) { throw new IllegalStateException("未设置促销策略"); } double finalPrice = strategy.calculatePrice(originalPrice); System.out.println("原价: ¥" + originalPrice + " -> 实付: ¥" + finalPrice); return finalPrice; } } // Client:客户端 public class Client { public static void main(String[] args) { double originalPrice = 200.0; CheckoutContext checkout = new CheckoutContext(); checkout.setStrategy(new FullReductionStrategy(100, 20)); checkout.executeCheckout(originalPrice); checkout.setStrategy(new DiscountStrategy(0.8)); checkout.executeCheckout(originalPrice); checkout.setStrategy(new DirectReductionStrategy(50)); checkout.executeCheckout(originalPrice); } }

关键体会

  • CheckoutContext不知道具体是哪种促销策略,它只面向PromotionStrategy接口编程。

  • 新增一种促销方式(如 "第二件半价"),只需新增一个implements PromotionStrategy的类,不需要修改CheckoutContext的代码。这符合开闭原则

  • 如果没有策略模式,结算代码里会充满if (type.equals("fullReduction")) { ... } else if (type.equals("discount")) { ... }的臃肿代码。


四、场景二:支付渠道策略(实际开发场景)

业务背景:系统需要支持多种支付方式:支付宝、微信支付、银行卡支付。每种支付方式的流程不同(支付宝需要调用支付宝 SDK,微信需要调用微信 SDK,银行卡需要调用银联接口),但对外提供的接口一致(pay(amount)refund(orderId))。客户端根据用户选择的支付方式动态切换策略。

说明:这是实际开发中策略模式的典型应用,也是软考下午题中 "多算法封装" 场景的代表。

4.1 代码实现
// Strategy:支付策略接口 public interface PaymentStrategy { boolean pay(String orderId, double amount); boolean refund(String orderId, double amount); } // ConcreteStrategy:支付宝支付 public class AlipayStrategy implements PaymentStrategy { @Override public boolean pay(String orderId, double amount) { System.out.println("[支付宝] 订单 " + orderId + " 支付 ¥" + amount); return true; } @Override public boolean refund(String orderId, double amount) { System.out.println("[支付宝] 订单 " + orderId + " 退款 ¥" + amount); return true; } } // ConcreteStrategy:微信支付 public class WechatPayStrategy implements PaymentStrategy { @Override public boolean pay(String orderId, double amount) { System.out.println("[微信支付] 订单 " + orderId + " 支付 ¥" + amount); return true; } @Override public boolean refund(String orderId, double amount) { System.out.println("[微信支付] 订单 " + orderId + " 退款 ¥" + amount); return true; } } // ConcreteStrategy:银行卡支付 public class BankCardStrategy implements PaymentStrategy { @Override public boolean pay(String orderId, double amount) { System.out.println("[银行卡] 订单 " + orderId + " 支付 ¥" + amount + "(调用银联接口)"); return true; } @Override public boolean refund(String orderId, double amount) { System.out.println("[银行卡] 订单 " + orderId + " 退款 ¥" + amount + "(原路退回)"); return true; } } // Context:支付上下文 public class PaymentContext { private PaymentStrategy strategy; public void setStrategy(PaymentStrategy strategy) { this.strategy = strategy; } public boolean executePay(String orderId, double amount) { if (strategy == null) { throw new IllegalStateException("未选择支付方式"); } System.out.println("开始支付..."); return strategy.pay(orderId, amount); } public boolean executeRefund(String orderId, double amount) { if (strategy == null) { throw new IllegalStateException("未选择支付方式"); } System.out.println("开始退款..."); return strategy.refund(orderId, amount); } } // Client public class Client { public static void main(String[] args) { PaymentContext payment = new PaymentContext(); String orderId = "ORD20240711001"; double amount = 299.0; payment.setStrategy(new AlipayStrategy()); payment.executePay(orderId, amount); payment.setStrategy(new WechatPayStrategy()); payment.executePay(orderId, amount); payment.setStrategy(new BankCardStrategy()); payment.executePay(orderId, amount); } }

五、场景三:排序算法策略(算法族封装)

业务背景:系统需要对一组数据进行排序,但排序算法需要根据数据规模和特性动态选择:数据量小用冒泡排序(简单),数据量大用快速排序(高效),数据基本有序用插入排序(最优)。使用策略模式封装不同的排序算法,Context 根据条件自动选择或允许客户端手动选择。

说明:这是策略模式在算法选择场景中的典型应用,也是软考上午题中 "算法替换" 场景的代表。

5.1 代码实现
import java.util.Arrays; // Strategy:排序策略接口 public interface SortStrategy { void sort(int[] data); } // ConcreteStrategy:冒泡排序 public class BubbleSortStrategy implements SortStrategy { @Override public void sort(int[] data) { System.out.println("[冒泡排序] 开始排序,数据量: " + data.length); for (int i = 0; i < data.length - 1; i++) { for (int j = 0; j < data.length - 1 - i; j++) { if (data[j] > data[j + 1]) { int temp = data[j]; data[j] = data[j + 1]; data[j + 1] = temp; } } } System.out.println("[冒泡排序] 完成: " + Arrays.toString(data)); } } // ConcreteStrategy:快速排序 public class QuickSortStrategy implements SortStrategy { @Override public void sort(int[] data) { System.out.println("[快速排序] 开始排序,数据量: " + data.length); quickSort(data, 0, data.length - 1); System.out.println("[快速排序] 完成: " + Arrays.toString(data)); } private void quickSort(int[] data, int low, int high) { if (low < high) { int pivot = partition(data, low, high); quickSort(data, low, pivot - 1); quickSort(data, pivot + 1, high); } } private int partition(int[] data, int low, int high) { int pivot = data[high]; int i = low - 1; for (int j = low; j < high; j++) { if (data[j] <= pivot) { i++; int temp = data[i]; data[i] = data[j]; data[j] = temp; } } int temp = data[i + 1]; data[i + 1] = data[high]; data[high] = temp; return i + 1; } } // Context:排序上下文(带自动选择逻辑) public class SortContext { private SortStrategy strategy; public void setStrategy(SortStrategy strategy) { this.strategy = strategy; } public void autoSelectStrategy(int[] data) { if (data.length <= 50) { System.out.println("[上下文] 数据量较小,自动选择冒泡排序"); this.strategy = new BubbleSortStrategy(); } else { System.out.println("[上下文] 数据量较大,自动选择快速排序"); this.strategy = new QuickSortStrategy(); } } public void executeSort(int[] data) { if (strategy == null) { autoSelectStrategy(data); } strategy.sort(data); } } // Client public class Client { public static void main(String[] args) { SortContext sorter = new SortContext(); int[] smallData = {5, 3, 8, 1, 2}; sorter.executeSort(smallData); System.out.println(); int[] largeData = new int[1000]; for (int i = 0; i < largeData.length; i++) { largeData[i] = (int) (Math.random() * 10000); } sorter.executeSort(largeData); System.out.println(); int[] data = {9, 7, 5, 3, 1}; sorter.setStrategy(new BubbleSortStrategy()); sorter.executeSort(data); } }

六、三种场景对比与演进思路

维度场景一:电商促销场景二:支付渠道场景三:排序算法
ContextCheckoutContext(结算上下文)PaymentContext(支付上下文)SortContext(排序上下文)
StrategyPromotionStrategy(促销策略)PaymentStrategy(支付策略)SortStrategy(排序策略)
ConcreteStrategyFullReductionDiscountDirectReductionAlipayWechatPayBankCardBubbleSortQuickSort
策略切换方式客户端手动setStrategy()客户端手动setStrategy()支持自动选择 + 手动设置
算法参数策略构造器传入(threshold、rate)无参(内部调用 SDK)无参(操作传入的数据)
返回值double(最终价格)boolean(成功/失败)void(直接修改数组)
新增策略成本新增类,不改 Context新增类,不改 Context新增类,不改 Context
软考考法下午大题(补全 calculatePrice)下午大题(补全 pay/refund)上午选择题(识别算法替换)

七、策略模式 vs 状态模式 vs 模板方法模式:核心对比

对比项策略模式状态模式模板方法模式
模式分类行为型行为型行为型
核心思想封装算法族,让它们可以相互替换封装状态转换,状态改变时行为改变定义算法骨架,子类实现某些步骤
切换触发者客户端主动调用setStrategy()切换状态内部根据条件自动转换到下一个状态父类控制流程,子类被动参与
类关系Context组合Strategy(聚合关系)Context组合State(聚合关系)抽象类继承(子类 extends 父类)
客户端感知客户端知道有哪些策略,主动选择客户端不知道状态转换细节客户端不知道模板方法的存在
代码结构一个 Context + N Strategy 实现类一个 Context + N State 实现类 + 可能的状态机一个抽象类 + N 子类
新增扩展新增策略类,不改 Context新增状态类,可能需修改状态转换逻辑新增子类,实现抽象方法
典型应用促销策略、支付方式、排序算法订单状态机(待支付→已支付→已发货)、游戏角色状态数据导入模板、报表生成模板
软考判断看到 "多种算法可替换"、"客户端选择" → 策略看到 "状态转换"、"自动改变行为" → 状态看到 "算法骨架"、"子类实现特定步骤" → 模板方法

记忆口诀:策略是 "客户端选算法"(主动切换),状态是 "状态自己变"(自动转换),模板方法是 "父类定骨架子类填坑"(继承实现)。


八、软考高频考点与易混淆辨析

8.1 高频考点
考点内容
模式分类行为型模式(GoF 23 正式成员)
核心三角色Context(上下文)、Strategy(抽象策略)、ConcreteStrategy(具体策略)
核心思想封装算法族,让它们可以相互替换,算法的变化独立于使用算法的客户
Context 与 Strategy 关系组合/聚合(Context 持有 Strategy 引用,不是继承)
动态切换通过setStrategy()方法在运行时更换策略
设计原则开闭原则:新增策略只需增加 ConcreteStrategy,无需修改 Context
消除 if-else策略模式的核心价值之一:避免 Context 中出现大量条件判断语句
与状态模式区别策略:客户端主动选择;状态:状态内部自动转换
与模板方法区别策略:组合 + 算法整体替换;模板方法:继承 + 算法骨架固定、部分步骤替换
适用场景① 多种算法/策略需要动态切换 ② 需要避免多重条件判断 ③ 算法需要独立于客户端变化
8.2 易混淆辨析:策略 vs 状态 vs 模板方法
对比项策略模式状态模式模板方法模式
UML 结构Context 组合 StrategyContext 组合 State抽象类定义模板,子类继承
切换控制权外部(客户端/setter)内部(状态对象内部转换)无切换(子类固定)
客户端角色客户端选择策略并注入客户端触发事件,状态自动流转客户端调用模板方法
类数量1 Context + N Strategy1 Context + N State + 可能的状态机1 抽象类 + N 子类
关系类型组合/聚合组合/聚合继承
软考考法代码填空(补全 setStrategy + execute)代码填空(补全状态转换逻辑)代码填空(补全子类实现特定步骤)

九、真题风格模拟与代码填空

模拟题 1(上午选择题)

以下关于策略模式的叙述中,正确的是()。

A. 策略模式属于结构型模式,主要用于封装对象的创建逻辑

B. 在策略模式中,Context 通过继承 Strategy 来获得算法实现

C. 策略模式定义了一系列算法,把它们封装起来,并且使它们可以相互替换,让算法的变化独立于使用算法的客户

D. 策略模式与状态模式的核心区别在于:策略模式由状态内部自动转换,状态模式由客户端主动选择

答案:C

解析

  • A 错误:策略模式属于行为型模式,不是结构型。它封装的是算法/行为,不是对象的创建。

  • B 错误:Context 通过组合/聚合(持有 Strategy 引用)来使用算法,不是继承。如果用继承,就无法在运行时动态切换策略。

  • C 正确:这是策略模式的核心定义(GoF 原书定义)。

  • D 错误:说反了。策略模式由客户端主动选择setStrategy()),状态模式由状态内部自动转换(状态对象根据条件改变 Context 的状态)。


模拟题 2(下午代码填空 — 补全 Context 的 setStrategy 和 execute)

某系统使用策略模式实现不同的数据验证策略。ValidationStrategy接口提供validate(String data)方法。LengthValidationStrategyRegexValidationStrategy是具体策略。ValidatorContext是上下文。请补全(1)~(4)。

// Strategy interface ValidationStrategy { boolean validate(String data); } // ConcreteStrategy:长度验证 class LengthValidationStrategy implements ValidationStrategy { private int min; private int max; public LengthValidationStrategy(int min, int max) { this.min = min; this.max = max; } public boolean validate(String data) { return data != null && data.length() >= min && data.length() <= max; } } // ConcreteStrategy:正则验证 class RegexValidationStrategy implements ValidationStrategy { private String pattern; public RegexValidationStrategy(String pattern) { this.pattern = pattern; } public boolean validate(String data) { return data != null && data.matches(pattern); } } // Context class ValidatorContext { private (1)______ strategy; public void (2)______(ValidationStrategy strategy) { this.strategy = strategy; } public boolean (3)______(String data) { if (strategy == null) { throw new IllegalStateException("未设置验证策略"); } return (4)______; } } public class Client { public static void main(String[] args) { ValidatorContext validator = new ValidatorContext(); validator.setStrategy(new LengthValidationStrategy(6, 20)); System.out.println(validator.executeValidate("hello123")); } }

答案

  • (1)ValidationStrategy

  • (2)setStrategy

  • (3)executeValidate(或validate

  • (4)strategy.validate(data)

阅卷要点

  • (1) 必须是ValidationStrategy(抽象策略接口类型),体现面向接口编程。不能写LengthValidationStrategyRegexValidationStrategy等具体类。

  • (2) 必须是setStrategy,这是策略模式 Context 的标准方法名,用于动态注入/更换策略。

  • (3) 可以是executeValidatevalidateexecute等,表示执行操作的方法名。软考中通常用executeXxx()contextInterface()

  • (4) 必须是strategy.validate(data),将操作委托给策略对象执行。这是策略模式的核心:Context 不直接实现算法,而是委托给 Strategy。


模拟题 3(下午代码填空 — 补全 ConcreteStrategy 和 Context 调用)

某系统使用策略模式实现不同的运费计算策略。ShippingStrategy接口提供calculateShipping(double weight, double distance)方法。StandardShippingStrategyExpressShippingStrategy是具体策略。请补全(1)~(2)。

// Strategy interface ShippingStrategy { double calculateShipping(double weight, double distance); } // ConcreteStrategy:标准快递 class StandardShippingStrategy implements ShippingStrategy { public double calculateShipping(double weight, double distance) { return 10 + weight * 2 + distance * 0.5; } } // ConcreteStrategy:顺丰快递(需要补全) class ExpressShippingStrategy (1)______ ShippingStrategy { public double calculateShipping(double weight, double distance) { return (2)______; } } // Context class OrderContext { private ShippingStrategy strategy; public void setStrategy(ShippingStrategy strategy) { this.strategy = strategy; } public double calculateTotal(double weight, double distance) { return strategy.calculateShipping(weight, distance); } } public class Client { public static void main(String[] args) { OrderContext order = new OrderContext(); order.setStrategy(new ExpressShippingStrategy()); double shipping = order.calculateTotal(2.5, 100); System.out.println("运费: ¥" + shipping); } }

答案

  • (1)implements

  • (2)15 + weight * 3 + distance * 1(或等价表达式)

阅卷要点

  • (1) 必须是implements,具体策略类实现策略接口。如果写extends零分(除非 Strategy 是抽象类,但这里是 interface)。

  • (2) 必须是根据题干描述的算法表达式。题目说 "首重 15 元,续重每公斤 3 元,每公里 1 元",所以表达式为15 + weight * 3 + distance * 1。如果写10 + weight * 2 + distance * 0.5(标准快递的算法)会零分


十、常见陷阱与注意事项

陷阱 1:误认为策略是结构型模式

策略模式属于行为型模式,因为它关注的是对象之间的行为/算法交互(Context 将行为委托给 Strategy),而不是类与类之间的结构关系。软考上午题如果问"以下属于结构型模式的是",选项里出现"策略"不能选

陷阱 2:Context 继承 Strategy 而不是组合

这是软考最高频的失分点。策略模式的核心是组合/聚合

  • ❌ 错误:class Context extends Strategy(继承,静态绑定,无法动态切换)

  • ✅ 正确:class Context { private Strategy strategy; }(组合,运行时注入)

软考代码填空里,Context 必须持有private Strategy xxx字段,并通过setStrategy()方法注入。如果 Context 继承 ConcreteStrategy,那就失去了策略切换的意义。

陷阱 3:与状态模式混淆

这是软考最难的辨析题之一。两者的 UML 结构几乎完全相同:

  • 都有 Context 类

  • Context 都组合一个接口(Strategy / State)

  • 都有多个具体实现类

终极区分方法:看切换的触发者。

  • 策略模式客户端主动调用setStrategy()选择算法。Context 通常不自己决定切换。

  • 状态模式状态对象内部根据业务条件自动调用context.setState()转换到下一个状态。客户端通常只触发事件,不直接选择状态。

如果题干说 "客户端根据条件选择不同的算法" → 策略。如果题干说 "对象内部状态改变时自动改变行为" → 状态。

陷阱 4:与模板方法模式混淆
策略模式模板方法模式
组合关系(Context 持有 Strategy)继承关系(子类 extends 抽象类)
算法整体替换(换一个 Strategy 对象)算法骨架固定,只替换部分步骤
运行时动态切换编译时静态绑定(子类固定)
新增策略:新增类 +setStrategy()新增模板:新增子类 + 继承

如果类图里是组合关系 + 可以动态替换 → 策略。如果是继承关系 + 抽象类定义模板方法 → 模板方法。

陷阱 5:策略类直接暴露给客户端,绕过 Context

虽然策略模式允许客户端直接创建ConcreteStrategy对象,但规范的做法是客户端通过 Context 来使用策略(context.setStrategy(new XxxStrategy()); context.execute();)。如果客户端直接调用strategy.algorithm(),那就失去了 Context 作为统一入口的意义。软考代码填空里,如果题目给出了 Context 类,客户端应该通过 Context 调用,而不是直接调用 Strategy。

陷阱 6:Context 内部用 if-else 选择策略

这是违背策略模式初衷的写法。策略模式的目的就是消除 Context 中的 if-else

  • ❌ 错误:

public double execute(double price) { if (strategy instanceof FullReductionStrategy) { ... } else if (strategy instanceof DiscountStrategy) { ... } }
  • ✅ 正确:

java

public double execute(double price) { return strategy.calculatePrice(price); // 直接委托,无需判断类型 }

软考阅卷时,如果 Context 的execute()方法里出现了instanceofif-else判断策略类型,通常会扣分,因为这违背了策略模式的设计意图。

陷阱 7:忘记在 Context 中定义 setStrategy 方法

策略模式的核心是动态切换setStrategy()方法是实现动态切换的关键。如果 Context 中只有构造器注入策略(没有 setter),那就只能在创建时确定策略,无法在运行时切换。虽然这种 "静态策略" 也是策略模式的一种用法,但软考通常考察的是动态切换的场景,代码填空里必须包含setStrategy()方法。


十一、总结

要点内容
定义定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户
分类行为型模式(GoF 23 正式成员)
核心三角色Context(上下文)、Strategy(抽象策略)、ConcreteStrategy(具体策略)
核心思想封装算法族,通过组合让 Context 在运行时动态切换策略
Context 与 Strategy 关系组合/聚合private Strategy strategy+setStrategy()
动态切换通过setStrategy()在运行时更换策略
设计原则开闭原则:新增策略只需增加 ConcreteStrategy,无需修改 Context
消除 if-else避免 Context 中出现大量条件判断,将算法选择推迟到客户端
与状态模式区别策略:客户端主动选择;状态:状态内部自动转换
与模板方法区别策略:组合 + 算法整体替换;模板方法:继承 + 算法骨架固定
软考重点代码填空(补全 Context 的setStrategy()+execute()委托调用);与状态模式的辨析(最高频);与模板方法的辨析
答题技巧看到 "多种算法可替换"、"动态切换"、"避免 if-else"、"客户端选择策略" → 策略;看到 Context 组合 Strategy +setStrategy()→ 确认策略

系列预告:下一篇将讲状态模式—— 当对象的行为取决于它的状态,且状态转换需要自动触发时,如何将状态封装为独立的类,让状态自己管理转换逻辑。策略与状态的辨析是软考高频考点,咱们下回重点拆解。咱们下回见。

http://www.cnnetsun.cn/news/3292808.html

相关文章:

  • 腾讯Hy3大模型实战:MoE架构解析与完整部署指南
  • C语言中的for循环,看这一篇就够了!
  • 终极指南:如何用GBFR Logs伤害统计工具优化《碧蓝幻想:Relink》团队输出
  • 多肽定制品纯度选择
  • PostgreSQL 19 Beta 值得测吗?并行 Autovacuum、REPACK 到 WAIT FOR LSN 看生产影响
  • 5分钟搞定华硕笔记本矩阵屏:用G-Helper打造专属动画与GIF播放效果
  • GTAIV.EFLC.FusionFix终极指南:如何让《侠盗猎车手4》焕发新生
  • 云固件 v1.6.23942 混合模式部署:3步完成UEFI+GPT本地硬盘引导集成
  • [CirclePupilAnimation节点]原理解析与实际应用
  • Neo4j Cypher 5.x 实战:3类复杂路径查询与性能调优对比
  • 3an推客超全常见问题答疑|电商运营新手必备实操指南
  • 为什么Playnite是游戏玩家的终极统一启动器?3步打造你的专属游戏中心
  • 直接序列扩频系统同步实战:滑动相关器捕获与延迟锁相环跟踪的2个关键步骤
  • Skill 太多、太乱、还不安全?还不知道哪些是适合自己行业的skill?只安装一个可信路由 Skill 就够了
  • FPGA UART 串口通信:3种电平标准(TTL/RS232/RS485)对比与选型指南
  • STM32F103C8T6 智能输液系统实战:红外滴速检测与步进电机PID控制
  • Visual C++运行库一键修复:3分钟彻底解决Windows软件启动问题的终极方案
  • 112、数据增强技巧:如何构建高质量的超分训练数据集
  • 绿盟一面面经分享
  • Claude Code国内可用指南:Node.js环境+CCSwitch路由配置实战
  • ubuntu 20.04 ros1 noetic环境复现 lego-loam 过程出现 mapOptmization-7] process has died 问题解决(个人经验)
  • HAC++:3D高斯泼溅模型超百倍压缩算法原理与实战部署
  • UE日志系统全解析:从基础调试到高级性能优化实战
  • 具身智能领域常见机器人平台与数据格式
  • 【DeepSeek内容过滤机制深度解密】:20年AI安全专家首度公开3层过滤架构与实时拦截逻辑
  • Hadoop HDFS 与 Linux 本地文件系统操作对比:10 个核心命令的差异与实战
  • 2026免费数字人平台怎么选?试用入口、导出权限、商用边界、后续成本一次看懂
  • NetworkX 2.8.8 实战:Python 构建 ER/WS/BA 三大网络模型,5分钟生成可视化对比图
  • TLA2518与dsPIC33EP构建高精度数据采集系统
  • 高精度信号采集系统设计与AD7175-8应用实战