层之间的反向依赖问题

时间:2010-09-06 12:27:43

标签: java dependencies layer decoupling

我正在为硬件安装(水循环系统)构建一个控制系统。我把它设计成两层:硬件描述层和控制层。

+----------------------------------------------+
|    Control (enables manipulation of devices) |
+----------------------------------------------+
        | uses (decorates)
        v
+---------------------------------------+  (de)serialize  +------------+
|            HW Description             |<--------------->| Files / DB |
| (stores physical layout, cabling etc) |                 +------------+
+---------------------------------------+

硬件描述层包含硬件地图,描述管道如何连接到热交换器和其他设备。该层的数据可根据安装进行配置,并将在运行时读入。因此,硬件描述层中的所有类都应该以某种方式可序列化(通过Hibernate /序列化到XML等)。

控制层将用智能装饰硬件描述层类,因此热交换器将例如获得与之关联的HeatExchangerController。

在这个系统中,控制层中的实体可能需要通过硬件描述找出他们最近的邻居,所以热交换控制器可能会做类似的事情

HeatExchangerController neighbour = this.getHeatExchanger().getInputPipe().getOtherSide().getHeatExchanger().getController();
neighbour.notify(highLoadAlert);

问题是这使得下层(硬件层)意识到它上面的智能(其控制器)。这不仅打破了层之间的单向依赖规则,而且由于所有硬件描述类都应该是可序列化的,这使代码变得复杂,因为对更高层的所有引用都需要是可选的,声明为瞬态等。

现在我有点陷入困境,试图通过像这样的硬件描述层使控件可用,或者是否有任何其他方法可以决定是否是好主意。我只能想到一种方法,它涉及镜像和委派几乎所有的硬件描述层,这似乎是侵入性的好方法。

所以我的问题是,如果你们中任何人都认识到这种情况并且有任何提示/经验。它有名字吗?它是否有任何良好的模式/最佳实践,是否还有其他知名的图书馆/框架也曾经解决过这种情况?

谢谢。

4 个答案:

答案 0 :(得分:0)

采用域驱动的方法。

如果您也垂直打破系统(域)。然后,这些垂直组件可以通过控制器相互通信,而不是其他任何东西。保持每个域内的水平层,并且分层在域内是垂直的,并且每个域彼此隔离,因为它们只能通过控制器进行通信。

答案 1 :(得分:0)

不太确定你的问题是什么。如果您不想在硬件类中使用getController()方法,则可以在弱哈希映射中存储硬件 - >控制器映射

public class Controller

    static WeakHashMap<Hardware,Controller> map = ...

    static public Controller of(Hardware hw){ return map.get(hw); }

    Controller(Hardware hw)
    {
        map.put(hw, this);
    }

很多时候,人们喜欢添加“方便”的方法,不必担心依赖性的复杂性

user.getThis()
user.getThat()
user.getTheOthers()

虽然User类是核心类,但它不应该知道This,That和The Others。现在,lof代码依赖于User类,而User类依赖于许多其他类。最终结果是应用程序中的每个类都依赖于其他所有类,这是一个混乱的大球。

答案 2 :(得分:0)

您没有向我们展示从硬件描述中分离控制器逻辑可以获得什么好处。你确定这种分离是值得的吗?

听起来你正在构建Anemic Domain Model

答案 3 :(得分:0)

这是我想到的复杂解决方案。它在HW层的顶部添加了一个装饰层,它将控制层的链接添加到每个HW对象:

                                                                 -+
+--------------------------+               +-----------------+    | 
| HeatExchangerController  |               | PipeController  |     > Controller Layer
+--------------------------+               +-----------------+    |
            ^ 1 controller                        ^ 1 controller -+
            |                                     |
            v 1 heatExchanger                     v 1 pipe       -+
+---------------------------+  inputPipe 1 +------------------+   |
| ControlAwareHeatExchanger |--------------| ControlAwarePipe |    > Decorated HW Layer
+---------------------------+ 1 otherSide  +------------------+   |
            |                                     |              -+
            v 1 realExchanger                     v 1 realPipe   -+
+---------------------------+  inputPipe 1 +------------+         |
|      HeatExchanger        |--------------| Pipe       |          > HW Layer
+---------------------------+ 1 otherSide  +------------+         |
                                                                 -+

装饰图层将包含如下代码:

class ControlAwareHeatExchanger {
  private final HeatExchanger realExchanger;
  private final ControlAwarepipe inputPipe;

  public ControlAwareHeatExchanger(HeatExchanger decoratee) {
    realExchanger = decoratee;
    inputPipe = new ControlAwarePipe(decoratee.getInputPipe());
  }

  public ControlAwarePipe getInputPipe() {
    return inputPipe;
  }

  ...
}      

这样你就可以:

ControlAwareHeatExchanger controlHE = heatExchangerController.getHeatExchanger();
ControlAwarePipe controlInputPipe = controlHE.getInputPipe();
ControlAwareHeatExchanger otherHE = controlInputPipe.getOtherSide();
HeatExchangerController otherController = otherHE.getController();

因此,你可以下到装饰的hw层,跳转,然后再次返回控制器层,所有这些都没有hw层知道控制层。

但是正如您所看到的,您需要镜像所有连接并装饰整个HW层以实现此目的。很多代表团都会参与其中。想法?