You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重构仅含常量与纯函数的类:是否误用面向对象抽象?

你的面向对象抽象确实存在误用,重构方案如下

问题分析

  • 混淆实体与逻辑职责:每个Subject子类既承载课程数据(名称、学分),又负责依赖判断逻辑,但所有子类都是无状态的,实例化它们完全多余——本质是在用类模拟枚举+静态方法,违背了面向对象“封装状态与行为”的核心思想。
  • 抽象类设计冗余:Subject强制子类实现的属性和方法,并未利用实例状态,反而导致每个课程都要重复编写无意义的模板代码。
  • 依赖逻辑硬编码且重复:高阶课程的依赖列表都硬编码在子类方法中,新增或修改课程时需要重复编写相似逻辑,维护成本高。

重构方案

核心思路:拆分职责,配置化管理

  1. 分离数据与逻辑:把课程元数据(名称、学分)和依赖判断逻辑拆分为独立模块,各自承担单一职责。
  2. 配置化依赖关系:将课程的前置依赖从代码中抽离,用配置方式维护,避免硬编码带来的维护负担。

重构后的代码

using System;
using System.Collections.Generic;
using System.Linq;

// 课程类型枚举,统一管理课程标识
public enum CourseType
{
    CalculusI,
    Algebra,
    CalculusII,
    CalculusIII
}

// 课程元数据类,专门存储课程基础信息与依赖关系
public class CourseMetadata
{
    public CourseType Type { get; set; }
    public string Name { get; set; }
    public int Credit { get; set; }
    public List<CourseType> Prerequisites { get; set; } = new List<CourseType>();
}

// 课程依赖服务,专门处理依赖判断逻辑
public class CoursePrerequisiteService
{
    private readonly Dictionary<CourseType, CourseMetadata> _courseMap;

    public CoursePrerequisiteService(List<CourseMetadata> courseMetadatas)
    {
        _courseMap = courseMetadatas.ToDictionary(m => m.Type);
    }

    // 递归查找目标课程的第一个未完成前置依赖
    public CourseMetadata FindMissingPrerequisite(CourseType targetCourse, List<CourseType> learnedCourses)
    {
        var targetMetadata = _courseMap[targetCourse];
        
        foreach (var prerequisite in targetMetadata.Prerequisites)
        {
            var missing = FindMissingPrerequisite(prerequisite, learnedCourses);
            if (missing != null)
            {
                return missing;
            }
            
            if (!learnedCourses.Contains(prerequisite))
            {
                return _courseMap[prerequisite];
            }
        }
        
        return null;
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        // 集中配置所有课程的元数据与依赖关系
        var courseMetadatas = new List<CourseMetadata>
        {
            new CourseMetadata { Type = CourseType.CalculusI, Name = "MTH101", Credit = 3 },
            new CourseMetadata { Type = CourseType.Algebra, Name = "MTH201", Credit = 3 },
            new CourseMetadata { Type = CourseType.CalculusII, Name = "MTH102", Credit = 3, Prerequisites = { CourseType.CalculusI } },
            new CourseMetadata { Type = CourseType.CalculusIII, Name = "MTH103", Credit = 3, Prerequisites = { CourseType.CalculusII } }
        };

        var service = new CoursePrerequisiteService(courseMetadatas);
        var learnedCourses = new List<CourseType> { CourseType.Algebra };
        
        var missingCourse = service.FindMissingPrerequisite(CourseType.CalculusIII, learnedCourses);
        if (missingCourse != null)
        {
            Console.WriteLine(missingCourse.Name); // 输出 MTH101
        }
        else
        {
            Console.WriteLine("已满足所有前置条件");
        }
    }
}

重构优势

  • 职责清晰:元数据类存信息,服务类处理逻辑,符合单一职责原则。
  • 维护成本低:新增/修改课程只需调整配置,无需改动逻辑代码。
  • 效率更高:避免了无意义的类实例化,代码简洁且易于理解。

内容的提问来源于stack exchange,提问作者FEEDC0DE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 01:05:36