0

0

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

煙雲

煙雲

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

|

604人浏览过

|

来源于php中文网

原创

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

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

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

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

常见错误是把策略接口设计得像配置类: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 更易测、更易换。

笔头写作
笔头写作

AI为论文写作赋能,协助你从0到1。

下载
  • 不要在业务代码里 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 支持多种策略接口(如 ISortStrategyICompressStrategy),用接口继承或组合,而不是泛型类型参数
  • 泛型策略类(如 SortStrategy<t></t>)适合做基类,但必须确保子类能被 DI 容器识别并注册,否则会因类型擦除导致解析失败

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

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

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

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

180

2024.05.11

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

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

224

2025.12.18

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

817

2023.08.22

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

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

401

2023.09.04

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

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

553

2023.08.03

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

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

216

2023.09.04

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

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

1553

2023.10.24

字符串介绍
字符串介绍

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

640

2023.11.24

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

561

2026.02.13

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9.7万人学习

C 教程
C 教程

共75课时 | 4.8万人学习

C++教程
C++教程

共115课时 | 18.3万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号