C# 如何用工厂方法模式设计游泳比赛排位系统?
——以灵活排位策略实现为例
一、系统核心设计思想
通过工厂方法模式解耦赛事类型与排位策略,实现以下灵活扩展:
1. 动态创建排位策略
PrelimEvent
(预赛)→ 生成CircleSeeding
(循环排位)TimedFinalEvent
(计时决赛)→ 生成StraightSeeding
(直接排位)
// 预赛返回循环排位策略
public override Seeding getSeeding() {return new CircleSeeding(swimmers, numLanes);
}
2. 统一抽象接口
- 抽象基类
Event
定义公共接口:isPrelim()
,isFinal()
,isTimedFinal()
标识赛事类型getSeeding()
工厂方法由子类实现具体策略
二、排位算法实现差异
策略类型 | 适用赛事 | 核心逻辑 |
---|---|---|
直接排位 | 计时决赛 | 按成绩降序分配泳道,快→慢居中排列 |
循环排位 | 预赛 | 继承直接排位后,对前3组泳道重新分配 |
1. 直接排位关键步骤
protected override void seed() {sortUpwards(); // 按成绩升序排序 // 计算分组:保证最后一组至少有3人 int lastHeat = count % numLanes;if(lastHeat < 3) lastHeat = 3; numHeats = (count - lastHeat) / numLanes + 1;
}
- 优势:确保高水平选手分散在不同组别,避免“死亡之组”。
2. 循环排位优化逻辑
protected override void seed() {base.seed(); // 先执行直接排位if(numHeats >= 2) {int circle = (numHeats >= 3) ? 3 : 2;// 重新分配前几组泳道:快慢交错避免扎堆for(int j=0; j<numLanes; j++) {for(int k=0; k<circle; k++) {swmrs[i].setLane(lanes[j]);swmrs[i++].seatHeat(numHeats - k);}}}
}
三、工厂方法的核心价值
1. 解决三类痛点
- 动态决策:运行时根据赛事类型选择排位策略(如预赛→循环排位)
- 扩展性:新增赛事类型(如决赛)只需派生新子类
- 局部化创建逻辑:将对象创建封装在子类,避免客户端代码冗余
2. 典型应用场景
- 工厂通过配置文件(如
500free.txt
)自动选择赛事类型 - 新增策略无需修改已有排位算法
四、实践启示
1. 模式选择时机
- 当系统需支持多维度变化(赛事类型×排位策略)时,工厂方法比简单工厂更符合开闭原则。
2. 性能优化点
- 循环排位复用直接排位的基础排序,减少重复计算
- 通过
lanes[j]
泳道池化降低对象创建开销
3. 扩展方向
- 添加
FinalEvent
类实现决赛专属排位策略 - 支持动态泳道数(如8道池vs10道池)
关键总结:工厂方法模式将“对象创建”提升为系统设计维度,通过抽象与实现的分离,让算法策略像乐高积木般自由组合——这正是应对体育赛事复杂规则演进的终极武器。