我正在研究一个模型,它可以用一堆不同的车辆做一些事情。
每辆车都应该做一些事情,但每种车辆类型做不同的事情。
所以我使用 .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
你可以实现一个枚举
ReportType
在 Vehicle
.想象一下 future 要求为肌肉车和家用车创建不同的报告。然后,您可以仅根据枚举值生成不同的报告,而不是深入研究继承。
关于c# - 在关联来自不同基类的派生类时避免双向依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63376767/