代码之家  ›  专栏  ›  技术社区  ›  Roman Nime Cloud

重构-打破依赖关系

  •  2
  • Roman Nime Cloud  · 技术社区  · 7 年前

    Racing-Car-Katas . 目标是重构一堆代码,使其遵循可靠的原则。

    我试着添加 Dependency Inversion Principle

    初始情况

    Alarm 是依赖关系吗 Sensor 这就产生了 psiPressureValue .

    public class Alarm {
        Sensor sensor = new Sensor();
    
        public void check()
        {
            double psiPressureValue = sensor.popNextPressurePsiValue();
            /* ... */
        }
    }
    

    想法

    public class Alarm {
        Sensor sensor;
    
        public Alarm() {
            this.sensor = new Sensor();
        }
    
        public Alarm(ISensor sensor) {
            this.sensor = sensor;
        }
    
        public void check()
        {
            double psiPressureValue = sensor.popNextPressurePsiValue();
            /* ... */
        }
    }
    

    报警 传感器

    public Alarm() {
        this.sensor = new Sensor();
    }
    

    但我的直觉告诉我这是代码气味。。

    如何在实际应用程序中处理这种依赖关系?

    3 回复  |  直到 7 年前
        1
  •  2
  •   Steven    7 年前

    依赖反转原理(DIP)指出:

    高级模块不应依赖于低级模块。

    但是通过定义创建 Sensor 然而,实现违反了DIP,因为 传感器

    public Alarm() {
        this.sensor = new Sensor();
    }
    

    如果需要让高级模块依赖于抽象(如附加构造函数所示),则无需添加默认构造函数。这样做只会将依赖关系拖到底层模块。由于最终应用程序和测试都应该使用重载构造函数,因此默认构造函数没有意义,只会导致紧密耦合,从而违反DIP。

    这不是理论上的练习。在实际应用中,应该遵循这一原则。一个设计良好的实际应用程序应用了SOLID原理,并使用依赖注入作为实现松耦合和DIP的方法。这将解耦模块,并允许在系统中组成完整的对象图 Composition Root

        2
  •  1
  •   displayName    7 年前

    为了不打破 Alarm Sensor

    1. 传感器 所使用的 报警
    2. 将它们放在一个(或多个)接口中;然后,
    3. 传感器 实现这些接口。

    第二种构造函数方法不是保护依赖关系的正确方法。它通过创建一个 班级。

    总是使用有效的 传感器 ISensor (而不是创建 传感器 直接)。

        3
  •  0
  •   bcperth    7 年前

    好的,你想打破警报和传感器之间的直接耦合。

    您提出的解决方案显示了两个构造函数,一个注入传感器对象(外部创建),另一个直接创建传感器对象。你应该放弃:

    public Alarm() {
        this.sensor = new Sensor();
    } 
    

    一般来说,创建依赖项的最常见选项如下所示。 将创建从属对象:

    2) 客户使用 委托方名称

    3) 客户使用 抽象工厂

    5) 从外部通过DI容器并注入客户机(DI)

    这是一个关键点 客户机不控制其从属项的创建方式。这就是“解释”这个词 ".

    但是,客户保留了“的控制权” ", " 抽象工厂 ".