在给定复杂继承的情况下,保持一致的松耦合
本文关键字:保持一致 耦合 情况下 复杂 继承 | 更新日期: 2023-09-27 17:59:18
为了进行松耦合和测试,我现在用接口和抽象类替换具体引用,但我很难理解以下场景:
假设我有两个具体的业务层对象,它们的唯一目的是调用数据访问逻辑方法,并在返回到控制器(ASP.NET MVC 4)之前对结果执行逻辑,称为FordCar
和CitroenCar
。它们都继承自一个Car
抽象类,该类继承自ICar
接口:
public interface ICar
{
ICarDAL DAL;
bool StartEngine();
bool StopEngine();
Driver ChangeDriver(Driver d);
}
public abstract class Car : ICar
{
private ICarDAL DAL;
public virtual Car(ICarDAL DALInstance)
{
this.DAL = DALInstance;
}
public virtual bool StartEngine()
{
return this.DAL.UpdateEngine(true);
}
public virtual bool StopEngine()
{
return this.DAL.UpdateEngine(false);
}
public virtual Driver ChangeDriver(Driver d)
{
return this.DAL.UpdateDriver(d);
}
}
因为DAL包含适用于所有汽车的逻辑,所以我也为此实现了一个接口和抽象类:
public interface ICarDAL<T>
{
T EFContext;
bool UpdateEngine(bool b);
Driver UpdateDriver(Driver d);
}
public abstract class CarDAL<T> : ICarDAL<T>
{
private T EFContext;
public virtual bool UpdateEngine(bool b)
{
try
{
using(T db = new T())
{
// Perform DB update
// return true
}
}
catch(Exception e)
{
// Handle and return false
}
}
// and so on..
}
现在说FordCar
有能力打开挡风玻璃加热,而CitroenCar
没有。这就是我忽略的地方,为了保持一致性,我希望我必须为FordCar
实现额外的小接口和抽象类,但我如何保持使用抽象CarDAL
类(因为它包含大多数常见功能),但在没有定义TurnOnScreenHeating()
时调用它?这需要一个特定于汽车类型的DAL类,这违背了我的目标。
我想我的问题是:考虑到许多域对象大多具有共享功能,在尝试松耦合和依赖注入时,我如何适应奇怪的唯一功能?
因为在我的控制器中,我希望这样做:
public class FordCarController : Controller
{
private Car BLLMethods;
public FordCarController()
{
// Init concrete type
this.BLLMethods = new FordCar();
}
public ActionResult DoHeating()
{
this.BLLMethods.TurnOnScreenHeating();
return View();
}
}
为复杂的情节和糟糕的标题道歉。
我有一些观察结果。我希望其中一两个能适用于你遇到的特定情况:
- 比起继承,通常更倾向于组合。换句话说,与其有一个继承自
Car
的CitroenCar
和FordCar
,不如有一个具有Make
属性的Car
来告诉你它是哪种车 - 与其将功能建立在您对特定类型汽车的了解之上,不如尝试将重点放在功能检查上。你可以采取几种不同的方法。例如:
- 使对象实现特定于特性的接口(
IHaveWindscreenHeater
) - 使主
ICar
类实现bool CanHeatWindscreen{get;}
属性和TurnOnScreenHeating()
方法。后一种方法要么什么都不做,要么在没有暖气的汽车上破例
- 使对象实现特定于特性的接口(
- 您调用控制器
FordController
的事实告诉我,您不能再松散地耦合这一点:您声明它是为了做与福特汽车相关的事情,所以即使您设法将它与代码中的FordCar
类解耦,您在概念上仍然是紧密耦合的。这可能比代码中的紧密耦合更危险。根据上面的观察#1,您可能只想使用一个处理所有Car
操作的CarController
类