news 2026/5/1 8:40:41

常用设计模式:策略模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
常用设计模式:策略模式

策略模式(Strategy Pattern)是一种行为设计模式,它允许你定义一系列算法,并将每个算法封装起来,使它们可以相互替换。下面介绍策略模式在 TypeScript 中的实现。

策略模式基本概念

策略模式包含三个主要部分:

Context(上下文):维护一个策略对象的引用

Strategy(策略接口):定义所有支持的算法的公共接口

ConcreteStrategy(具体策略):实现策略接口的具体算法

image

基础实现

1. 定义策略接口

// 策略接口

interface PaymentStrategy {

pay(amount: number): void;

}

2. 实现具体策略类

// 信用卡支付策略

class CreditCardPayment implements PaymentStrategy {

private cardNumber: string;

private name: string;

constructor(cardNumber: string, name: string) {

this.cardNumber = cardNumber;

this.name = name;

}

pay(amount: number): void {

console.log(`使用信用卡支付 $${amount}`);

console.log(`卡号: ${this.cardNumber}, 持卡人: ${this.name}`);

}

}

// PayPal支付策略

class PayPalPayment implements PaymentStrategy {

private email: string;

constructor(email: string) {

this.email = email;

}

pay(amount: number): void {

console.log(`使用PayPal支付 $${amount}`);

console.log(`邮箱: ${this.email}`);

}

}

// 加密货币支付策略

class CryptoPayment implements PaymentStrategy {

private walletAddress: string;

constructor(walletAddress: string) {

this.walletAddress = walletAddress;

}

pay(amount: number): void {

console.log(`使用加密货币支付 $${amount}`);

console.log(`钱包地址: ${this.walletAddress}`);

}

}

3. 创建上下文类

// 支付上下文

class PaymentContext {

private strategy: PaymentStrategy;

constructor(strategy: PaymentStrategy) {

this.strategy = strategy;

}

// 设置支付策略

setStrategy(strategy: PaymentStrategy): void {

this.strategy = strategy;

}

// 执行支付

executePayment(amount: number): void {

this.strategy.pay(amount);

}

}

4. 使用示例

// 使用示例

const paymentContext = new PaymentContext(new CreditCardPayment("1234-5678-9012", "张三"));

// 使用信用卡支付

paymentContext.executePayment(100);

// 切换到PayPal支付

paymentContext.setStrategy(new PayPalPayment("zhang@example.com"));

paymentContext.executePayment(200);

// 切换到加密货币支付

paymentContext.setStrategy(new CryptoPayment("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"));

paymentContext.executePayment(300);

更复杂的示例:排序策略

// 排序策略接口

interface SortStrategy<T> {

sort(items: T[]): T[];

}

// 冒泡排序策略

class BubbleSort<T> implements SortStrategy<T> {

sort(items: T[]): T[] {

console.log("使用冒泡排序");

const arr = [...items];

for (let i = 0; i < arr.length; i++) {

for (let j = 0; j < arr.length - i - 1; j++) {

if (arr[j] > arr[j + 1]) {

[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];

}

}

}

return arr;

}

}

// 快速排序策略

class QuickSort<T> implements SortStrategy<T> {

sort(items: T[]): T[] {

console.log("使用快速排序");

if (items.length <= 1) return items;

const pivot = items[0];

const left = [];

const right = [];

for (let i = 1; i < items.length; i++) {

if (items[i] < pivot) {

left.push(items[i]);

} else {

right.push(items[i]);

}

}

return [...this.sort(left), pivot, ...this.sort(right)];

}

}

// 排序上下文

class Sorter<T> {

private strategy: SortStrategy<T>;

constructor(strategy: SortStrategy<T>) {

this.strategy = strategy;

}

setStrategy(strategy: SortStrategy<T>): void {

this.strategy = strategy;

}

sort(items: T[]): T[] {

return this.strategy.sort(items);

}

}

// 使用示例

const numbers = [64, 34, 25, 12, 22, 11, 90];

const sorter = new Sorter<number>(new BubbleSort<number>());

console.log("排序前:", numbers);

console.log("排序后:", sorter.sort(numbers));

// 切换排序策略

sorter.setStrategy(new QuickSort<number>());

console.log("使用快速排序:", sorter.sort(numbers));

使用函数式编程的实现

TypeScript 也支持函数式风格的策略模式:

// 策略类型定义

type DiscountStrategy = (amount: number) => number;

// 具体策略函数

const noDiscount: DiscountStrategy = (amount: number) => amount;

const percentageDiscount = (percentage: number): DiscountStrategy =>

(amount: number) => amount * (1 - percentage / 100);

const fixedDiscount = (discount: number): DiscountStrategy =>

(amount: number) => Math.max(0, amount - discount);

// 上下文

class ShoppingCart {

private items: number[] = [];

private discountStrategy: DiscountStrategy = noDiscount;

addItem(price: number): void {

this.items.push(price);

}

setDiscountStrategy(strategy: DiscountStrategy): void {

this.discountStrategy = strategy;

}

getTotal(): number {

const subtotal = this.items.reduce((sum, price) => sum + price, 0);

return this.discountStrategy(subtotal);

}

}

// 使用示例

const cart = new ShoppingCart();

cart.addItem(100);

cart.addItem(50);

cart.addItem(30);

console.log("原价:", cart.getTotal()); // 180

cart.setDiscountStrategy(percentageDiscount(10)); // 9折

console.log("9折后:", cart.getTotal()); // 162

cart.setDiscountStrategy(fixedDiscount(50)); // 减50

console.log("减50后:", cart.getTotal()); // 130

策略模式的优点

开闭原则:可以引入新策略而不修改现有代码

消除条件语句:避免大量的 if-else 或 switch-case 语句

算法复用:可以在不同的上下文中复用策略

测试友好:每个策略都可以独立测试

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 9:53:59

【Agent】生成式隐式记忆 MemGen 源码解读

x01 背景MemGen 提出动态生成式记忆框架&#xff0c;由记忆触发器与记忆编织器两个轻量模块协同构成&#xff0c;旨在突破现有智能体记忆范式的局限。当前主流的记忆实现路径为&#xff1a;参数化记忆通过微调将经验编码进模型参数&#xff0c;虽能深度内化知识却易引发灾难性遗…

作者头像 李华
网站建设 2026/4/28 7:22:34

如何通过3个关键步骤诊断并优化3D重建质量问题?

如何通过3个关键步骤诊断并优化3D重建质量问题&#xff1f; 【免费下载链接】colmap COLMAP - Structure-from-Motion and Multi-View Stereo 项目地址: https://gitcode.com/GitHub_Trending/co/colmap 当你在使用COLMAP进行3D重建时&#xff0c;是否遇到过模型表面出现…

作者头像 李华
网站建设 2026/5/1 7:19:52

Asio异步编程(进阶):构建高性能网络应用的核心指南

从同步阻塞到异步非阻塞&#xff0c;这不仅是API的切换&#xff0c;更是一次编程思维的彻底革新。掌握Asio的异步模型&#xff0c;意味着你能够用更少的资源处理成千上万的并发连接。 当你已经能够熟练使用Asio编写同步网络程序后&#xff0c;下一步就是征服异步编程这座高峰。…

作者头像 李华
网站建设 2026/4/28 2:22:35

Ofd2Pdf终极教程:5分钟掌握OFD批量转PDF的完整方案

你是否曾经面对重要的OFD格式文档却束手无策&#xff1f;在行政办公、财务报销、教育学习等场景中&#xff0c;OFD文件虽然标准化但兼容性差&#xff0c;而PDF格式则拥有更好的跨平台支持。Ofd2Pdf正是为解决这一痛点而生的开源转换工具&#xff0c;让你轻松实现格式转换的无缝…

作者头像 李华
网站建设 2026/4/25 11:42:31

如何突破RPC性能瓶颈?FlatBuffers+gRPC超低延迟架构解析

如何突破RPC性能瓶颈&#xff1f;FlatBuffersgRPC超低延迟架构解析 【免费下载链接】flatbuffers FlatBuffers&#xff1a;内存高效的序列化库。 项目地址: https://gitcode.com/GitHub_Trending/fl/flatbuffers 开篇&#xff1a;性能危机的真实场景 想象一下这个场景&…

作者头像 李华