C# 如何用工厂方法模式设计游泳比赛排位系统?

------以灵活排位策略实现为例


一、系统核心设计思想

通过工厂方法模式解耦赛事类型与排位策略,实现以下灵活扩展:

1. 动态创建排位策略

  • PrelimEvent(预赛)→ 生成CircleSeeding(循环排位)
  • TimedFinalEvent(计时决赛)→ 生成StraightSeeding(直接排位)
csharp 复制代码
// 预赛返回循环排位策略 
public override Seeding getSeeding() {
    return new CircleSeeding(swimmers, numLanes);
}

2. 统一抽象接口

  • 抽象基类Event定义公共接口:
    • isPrelim(), isFinal(), isTimedFinal()标识赛事类型
    • getSeeding()工厂方法由子类实现具体策略

二、排位算法实现差异

策略类型 适用赛事 核心逻辑
直接排位 计时决赛 按成绩降序分配泳道,快→慢居中排列
循环排位 预赛 继承直接排位后,对前3组泳道重新分配

1. 直接排位关键步骤

csharp 复制代码
protected override void seed() {
    sortUpwards(); // 按成绩升序排序 
    // 计算分组:保证最后一组至少有3人 
    int lastHeat = count % numLanes;
    if(lastHeat < 3) lastHeat = 3; 
    numHeats = (count - lastHeat) / numLanes + 1;
}
  • 优势:确保高水平选手分散在不同组别,避免"死亡之组"。

2. 循环排位优化逻辑

csharp 复制代码
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. 典型应用场景

客户端 EventFactory TimedFinalEvent PrelimEvent StraightSeeding CircleSeeding

  • 工厂通过配置文件(如500free.txt)自动选择赛事类型
  • 新增策略无需修改已有排位算法

四、实践启示

1. 模式选择时机

  • 当系统需支持多维度变化(赛事类型×排位策略)时,工厂方法比简单工厂更符合开闭原则。

2. 性能优化点

  • 循环排位复用直接排位的基础排序,减少重复计算
  • 通过lanes[j]泳道池化降低对象创建开销

3. 扩展方向

  • 添加FinalEvent类实现决赛专属排位策略
  • 支持动态泳道数(如8道池vs10道池)

关键总结:工厂方法模式将"对象创建"提升为系统设计维度,通过抽象与实现的分离,让算法策略像乐高积木般自由组合------这正是应对体育赛事复杂规则演进的终极武器。