讲师中心 微信公众号
AI工具推荐 视频效率加速

C# 策略模式实现方法 C#如何封装可变的算法

轻婷同学_5837

轻婷同学_5837

发布时间:2026-02-18 10:30:12

|

624人浏览过

|

来源于php中文网

原创

策略接口应只定义行为契约,不包含状态字段或生命周期方法;策略注册须用ServiceProvider而非手动Dictionary;Context类仅负责分发,选择逻辑应抽离为独立选择器。

c# 策略模式实现方法 c#如何封装可变的算法

策略接口定义要聚焦行为契约,别塞状态字段

策略模式的核心是把算法的「变化点」抽象成接口,而不是提前规划所有可能的字段。比如你要封装不同排序逻辑,ISortStrategy 只该有 Sort(int[] data) 方法,别加 IsStable 或 MaxDepth 这类配置属性——这些属于具体策略内部实现细节,或应通过构造函数注入。

常见错误是把策略接口设计得像配置类:ISortStrategy 里塞一堆 get 属性,结果每个实现都返回默认值,徒增维护成本。

  • 接口方法参数尽量精简,必要时用 record 封装输入(如 SortOptions),但别让接口本身承担配置职责
  • 避免在接口中定义 Init()、Dispose() 等生命周期方法——策略实例应是无状态、可复用的
  • 如果算法需要外部服务(如日志、缓存),通过构造函数传入依赖,而非在接口里暴露 SetLogger(ILogger) 这类 setter

策略注册与解析要用 ServiceProvider,别手写 Dictionary + new

手动维护 Dictionary<string isortstrategy></string> 并用 new QuickSortStrategy() 填充,会带来硬编码、生命周期失控、测试困难三重问题。.NET 6+ 应直接用 IServiceCollection 注册策略族,再通过 IServiceProvider 解析。

例如注册多个排序策略:

services.AddSingleton<ISortStrategy, QuickSortStrategy>();
services.AddSingleton<ISortStrategy, MergeSortStrategy>();
services.AddSingleton<ISortStrategy, HeapSortStrategy>();

然后用 GetServices<isortstrategy>()</isortstrategy> 获取全部,或按名称解析(需配合 KeyedService):

services.AddKeyedSingleton<ISortStrategy, QuickSortStrategy>("quick");
services.AddKeyedSingleton<ISortStrategy, MergeSortStrategy>("merge");

运行时根据配置字符串选策略,比 if-else new 更易测、更易换。

C#
C#

"避开 C# 常见错误——空陷阱、异步陷阱、LINQ 陷阱及资源泄漏。"

下载
  • 不要在业务代码里 new 策略实例——这会让单元测试无法 mock 行为
  • 若策略需传参(如超时时间),用工厂委托注册:services.AddSingleton<isortstrategy>(sp => new QuickSortStrategy(timeout: 5000))</isortstrategy>
  • 注意作用域:无状态策略用 Singleton;带缓存或上下文的考虑 Scoped,但要确认线程安全

Context 类只做策略分发,不掺杂算法逻辑

SortContext 这类上下文类,唯一职责是接收输入、选策略、调用 Execute(),绝不该出现 if (data.Length 这种分支逻辑——那已经是策略选择规则,应抽成独立的 <code>IStrategySelector。

典型反例:

public class SortContext
{
    public void Sort(int[] data)
    {
        if (data.Length < 50) // ❌ 把选择逻辑写死在 Context 里
            new InsertionSort().Sort(data);
        else
            new QuickSort().Sort(data);
    }
}

正确做法是让 SortContext 依赖 IStrategySelector<isortstrategy></isortstrategy>,而选择器本身可基于数据特征、配置、甚至性能采样动态决定。

  • Context 构造函数只接受策略接口或策略工厂,不接受具体实现类型
  • 避免给 Context 加模板方法(如 BeforeSort() / AfterSort())——那是装饰器或管道的事,不是策略模式的职责
  • 如果策略执行需统一异常处理或日志,用中间件或包装器(如 LoggingSortStrategy),别污染 Context

泛型策略基类容易误用,慎用 TStrategy 约束

有人试图用泛型约束统一策略族,比如 class StrategyContext<tstrategy> where TStrategy : class, IStrategy</tstrategy>,结果发现无法在运行时切换 TStrategy ——泛型参数是编译期确定的。这种写法实际把策略“固化”了,失去动态性。

真正需要泛型的地方,是策略接口本身支持类型参数(如 ISortStrategy<t></t>),且所有实现都针对同一组泛型参数;或者用泛型工厂方法封装创建逻辑。

  • 别为了“看起来通用”而加泛型,先问:这个类型参数是否真会影响策略行为?是否所有策略实现都共用它?
  • 若只是想让 Context 支持多种策略接口(如 ISortStrategy 和 ICompressStrategy),用接口继承或组合,而不是泛型类型参数
  • 泛型策略类(如 SortStrategy<t></t>)适合做基类,但必须确保子类能被 DI 容器识别并注册,否则会因类型擦除导致解析失败

策略模式真正的复杂点不在语法,而在边界划分:什么算“算法”,什么算“策略选择逻辑”,什么算“上下文环境”。这三个层次一旦混在一起,再多的泛型和接口也救不了。

热门AI工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

相关专题

更多
什么是中间件
什么是中间件

中间件是一种软件组件,充当不兼容组件之间的桥梁,提供额外服务,例如集成异构系统、提供常用服务、提高应用程序性能,以及简化应用程序开发。想了解更多中间件的相关内容,可以阅读本专题下面的文章。

669

2024.05.11

Golang 中间件开发与微服务架构
Golang 中间件开发与微服务架构

本专题系统讲解 Golang 在微服务架构中的中间件开发,包括日志处理、限流与熔断、认证与授权、服务监控、API 网关设计等常见中间件功能的实现。通过实战项目,帮助开发者理解如何使用 Go 编写高效、可扩展的中间件组件,并在微服务环境中进行灵活部署与管理。

644

2025.12.18

ThinkPHP中间件机制与请求拦截处理实践
ThinkPHP中间件机制与请求拦截处理实践

本专题围绕 ThinkPHP 中间件体系展开,深入讲解中间件的定义、注册与执行流程。内容包括全局中间件与路由中间件的区别、请求前后处理逻辑、自定义中间件开发以及权限验证与日志处理应用。通过实际案例,帮助开发者掌握中间件在项目中的核心作用与最佳实践。

438

2026.03.31

sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

1138

2023.09.04

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1798

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2864

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6184

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

5989

2023.11.24

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

20

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn