给定复杂的继承,保持一致的松散耦合

时间:2014-04-22 15:36:24

标签: c# asp.net asp.net-mvc inheritance dependency-injection

出于松散耦合和测试的目的,我现在用接口和抽象类替换具体的引用,但是我无法理解以下场景:

假设我有两个具体的业务层对象,其唯一目的是在传递回控制器(ASP.NET MVC 4)之前调用数据访问逻辑方法并对结果执行逻辑,称为FordCar和{{ 1}}。它们都继承自CitroenCar抽象类,它继承自Car接口:

ICar

因为DAL包含适用于所有汽车的逻辑,我也为此实现了一个接口和抽象类:

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);
    }
}

现在说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?这需要特定于汽车类型的DAL类,这会击败我的目标。

我想我的问题是:给定大量具有共享功能的域对象,在尝试松散耦合和依赖注入时如何适应奇怪的独特功能?

对于我的控制器,我希望这样做:

TurnOnScreenHeating()

为复杂的情景和糟糕的头衔道歉。

1 个答案:

答案 0 :(得分:4)

我有一些观察。我希望他们中的一两个能适用于您遇到的具体情况:

  1. 支持组合优于继承通常更好。换句话说,您可以使用CitroenCar属性FordCar来告诉您,而不是从Car继承CarMake。它是哪种车。
  2. 尝试专注于功能检查,而不是将功能基于您对特定类型汽车的了解。您可以采取一些不同的方法。例如:
    1. 使对象实现特定于功能的接口(IHaveWindscreenHeater)。
    2. 使主ICar类实现bool CanHeatWindscreen{get;}属性,以及TurnOnScreenHeating()方法。后一种方法可以做任何事情,或者在没有暖气的汽车中抛出异常。
  3. 你正在给你的控制器FordController打电话的事实告诉我你不能再松散地说这个:你宣称要做与福特汽车有关的事情,所以即使你设法将它与代码中的FordCar类,你仍然在概念上紧密耦合。这可能比在代码中紧密耦合更危险。在上面观察#1之后,您可能只想使用一个处理所有CarController操作的Car类。