在给定复杂继承的情况下,保持一致的松耦合

本文关键字:保持一致 耦合 情况下 复杂 继承 | 更新日期: 2023-09-27 17:59:18

为了进行松耦合和测试,我现在用接口和抽象类替换具体引用,但我很难理解以下场景:

假设我有两个具体的业务层对象,它们的唯一目的是调用数据访问逻辑方法,并在返回到控制器(ASP.NET MVC 4)之前对结果执行逻辑,称为FordCarCitroenCar。它们都继承自一个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();
    }
}

为复杂的情节和糟糕的标题道歉。

在给定复杂继承的情况下,保持一致的松耦合

我有一些观察结果。我希望其中一两个能适用于你遇到的特定情况:

  1. 比起继承,通常更倾向于组合。换句话说,与其有一个继承自CarCitroenCarFordCar,不如有一个具有Make属性的Car来告诉你它是哪种车
  2. 与其将功能建立在您对特定类型汽车的了解之上,不如尝试将重点放在功能检查上。你可以采取几种不同的方法。例如:
    1. 使对象实现特定于特性的接口(IHaveWindscreenHeater
    2. 使主ICar类实现bool CanHeatWindscreen{get;}属性和TurnOnScreenHeating()方法。后一种方法要么什么都不做,要么在没有暖气的汽车上破例
  3. 您调用控制器FordController的事实告诉我,您不能再松散地耦合这一点:您声明它是为了做与福特汽车相关的事情,所以即使您设法将它与代码中的FordCar类解耦,您在概念上仍然是紧密耦合的。这可能比代码中的紧密耦合更危险。根据上面的观察#1,您可能只想使用一个处理所有Car操作的CarController