c# - 在关联来自不同基类的派生类时避免双向依赖

标签 c# dependencies polymorphism

我正在研究一个模型,它可以用一堆不同的车辆做一些事情。
每辆车都应该做一些事情,但每种车辆类型做不同的事情。
所以我使用 .NET Framework 以这种方式实现了它:

abstract class Vehicle
{
   abstract void DoStuff()
}

class Car : Vehicle
{
   override void DoStuff()
   {
       //Do some Car stuff here
   }
}

class Motorcycle : Vehicle
{
   override void DoStuff()
   {
       //Do some Motorcycle stuff here
   }
}
class Model
{
  RunModel(Vehicle[] vehicleCollection)
  {
    foreach(Vehicle currentVehicle in vehicleCollection)
    {
      currentVehicle.DoStuff()
    }
  }
}
这是我的程序的核心功能,它按预期工作。
现在我应该根据每辆车所做的事情输出报告。每种类型的车辆都应该输出不同类型的报告,所以我为它做了一个类似的解决方案:
abstract class Vehicle
{
   abstract void DoStuff();
   abstract Report GetReport();
}

class Car : Vehicle
{
   override Report GetReport()
   {
       return new CarReport(this);
   }
}

class Motorcycle : Vehicle
{
   override Report GetReport()
   {
       return new MotorcycleReport(this);
   }
}

abstract class Report
{
   int Foo {get; set;}

   Report (Vehicle _vehicle)
   {
       Foo = _vehicle.CommonProperty;
   }
      
}

class CarReport : Report
{
   string Bar {get; set;}
   CarReport(Car _car) : base(_car)
   {
       Bar = _car.CarPropoerty;
   }
}

class MotorcycleReport : Report
{
   bool Baz {get; set;}
   MotorcycleReport(Motorcycle _cycle) : base(_cycle)
   {
       Baz= _cycle.MotorcyclePropoerty;
   }
}
class Model
{
  RunModel(Vehicle[] vehicleCollection)
  {
    foreach(Vehicle currentVehicle in vehicleCollection)
    {
      currentVehicle.DoStuff()
      currentVehicle.GetReport()
    }
  }
}
这也可以正常工作,但问题是 Car 和 Motorcycle 现在依赖于 CarReport 和 MotorcycleReport。由于这是我的程序的非核心功能,并且报告结构在 future 版本中可能会发生很大变化,我想以报告依赖于车辆的方式实现它,但车辆不依赖于报告。
我尝试了一种获取车辆并输出正确报告的外部重载方法
或将抽象报告(或接口(interface) IReport)传递给 Vehicle “GetReport” 方法
但是由于我的 RunModel 方法不知道它正在处理什么类型的 Vehicle,所以我找不到将其映射到正确报告类型的方法。
有没有办法避免这种双向依赖?

最佳答案

保持核心域尽可能简单是对的。它应该只需要处理自己的复杂性,并尽可能少地受到外部干扰和依赖。
首先想到的是,即使继承可能对 Vehicle 有意义。等级制度。问题是,这对报告有意义吗?你会使用抽象库Report自己上课?仅具有共同属性的一种。
如果确实如此
您可以使用经理来承担创建Report 的责任。 s。

public class ReportManager
{
    public Report GetReport<T>(T vehicle) where T : Vehicle
    {
        switch (vehicle)
        {
            case Car car:
                return new CarReport(car);

            case Motorcycle motorcycle:
                return new MotorcycleReport(motorcycle);

            default:
                throw new NotImplementedException(vehicle.ToString());
        }
    }
}
你可以像这样使用它。
public class Model
{
    private readonly ReportManager _reportManager;

    public Model(ReportManager reportManager)
    {
        _reportManager = reportManager;
    }

    public List<Report> RunModel(Vehicle[] vehicles)
    {
        var reports = new List<Report>();

        foreach (var vehicle in vehicles)
        {
            vehicle.DoStuff();
            reports.Add(_reportManager.GetReport(vehicle));
        }

        return reports;
    }
}
如果没有
您可以将工作划分为两个单独的流程。
public class Model
{
    public List<CarReport> CarReports { get; private set; }
    public List<MotorcycleReport> MotorcycleReports { get; private set; }

    public void RunModel(Vehicle[] vehicles)
    {
        // 1. Do stuff
        foreach (var vehicle in vehicles)
        {
            vehicle.DoStuff();
        }
        // 2. Get reports
        CarReports = vehicles.OfType<Car>().Select(car => new CarReport(car)).ToList();
        MotorcycleReports = vehicles.OfType<Motorcycle>().Select(motorcycle => new MotorcycleReport(motorcycle)).ToList();
    }
}
区别
第一个方法返回一个基类列表。第二种方法在对象上存储不同类型的列表。一旦你有不同的类型,你不能再在一个类型化的集合中返回它们而不先向上转换。
最后的想法

Report structure may change a lot in future versions


你可以实现一个枚举 ReportTypeVehicle .想象一下 future 要求为肌肉车和家用车创建不同的报告。然后,您可以仅根据枚举值生成不同的报告,而不是深入研究继承。

关于c# - 在关联来自不同基类的派生类时避免双向依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63376767/

相关文章:

c# - Visual Studio 大型解决方案

maven - 不包括依赖的依赖

java - 如何让 Maven 依赖于运行时类路径而不是测试类路径?

java - 我可以强制 Maven 依赖项 A 使用特定版本的依赖项 B,同时使用不同版本的依赖项 B 吗?

c# - ASP .NET MVC 在每个字段级别禁用客户端验证

c# - 为什么 ThreadAbortException 不抛出 catch block

c++ - 数组随机访问 C++

polymorphism - 指定 Julia 函数只能采用内容属于特定类型的字典/数组的正确方法是什么?

c# - 如何在单元测试期间设置数据结构的内部状态?

java - 传承计划。我从哪说起呢?