依赖倒置原理是罗伯特.C.马丁提出来的,其中心思想如下:
高层模块不能依赖低层模块,两者都要依赖抽象。抽象不能依赖具体,具体要依赖抽象。
这个原理倒置了传统的高层模块依赖低层模块的观念,提出了高层或低层模块要依赖抽象,下面我们用一个三层协议栈的例设计子来详细说明下
该原理。
分以下三个步骤来说明:
- 初始设计
- 用依赖倒置原理来修改设计
- 依赖倒置的优点
初始设计
考察下面的无线电通信三层协议的代码,三层协议分别是:
- RLC物理层
- RLC数据链路层
- RLC网络层
每一层对应一个类, 代码骨架如下:
Layers
class RLC_Physical_Layer
{
RLC_Datalink_Layer *m_p_RLC_Datalink_Layer;
public:
void Device_Transmit(Datagram *p_Datagram)
{
Apply_Physical_Layer_Headers(p_Datagram);
Write_Message_To_Device(p_Datagram);
}
void Handle_Device_Receive(Datagram *p_Datagram)
{
Remove_Physical_Layer_Header(p_Datagram);
m_p_RLC_Datalink_Layer->Handle_Physical_Layer_Receive(p_Datagram);
}
};
class RLC_Datalink_Layer
{
RLC_Physical_Layer *m_p_RLC_Physical_Layer;
RLC_Network_Layer *m_p_RLC_Network_Layer;
public:
void Datalink_Transmit(Datagram *p_Datagram)
{
Process_Datalink_Transmit(p_Datagram);
m_p_RLC_Physical_Layer->Device_Transmit(p_Datagram);
}
void Handle_Physical_Layer_Receive(Datagram *p_Datagram)
{
Process_Datalink_Receive(p_Datagram);
m_p_RLC_Network_Layer->Handle_Network_Layer_Receive(p_Datagram);
}
};
class RLC_Network_Layer
{
RLC_Datalink_Layer *m_p_RLC_Datalink_Layer;
Application_Layer *m_p_Application_Layer;
public:
void Network_Transmit(Datagram *p_Datagram)
{
Process_Network_Layer_Transmit(p_Datagram);
m_p_RLC_Datalink_Layer->Datalink_Transmit(p_Datagram);
}
void Handle_Datalink_Layer_Receive(Datagram *p_Datagram)
{
Process_Network_Layer_Receive(p_Datagram);
m_p_Application_Layer->Handle_Application_Receive(p_Datagram);
}
};
这不是一个好的设计,因为有如下限制:
- 所有层都是相互依赖的,每个层的代码都需要包含其它层的头文件。
- 层之间的联系是固定的,要实现一个新的协议的话,必须重新改写层的联系。
- 一个层的被改变就会影响到其它层。
要解决以上问题, 就必须引入一个抽象层,让这些层都去依赖抽象层, 这就是依赖倒置原理的具体应用。
用依赖倒置原理来修改设计
先来设计一个抽象层, 该抽象层的要点如下:
- 构造函数有两个参数,一个是上层类抽象,一个是下层类抽象,这样保证了该层跟其它层的关系。
- 对上层发送过来的消息进行特定处理,处理完毕后调用底层传送接口发送给底层。
- 对低层接收到的信息做特定处理,处理完毕后就调用上层接收处理接口让上层进行处理。
下面的代码设计完全解耦合了三层的关系,所有层都只依赖于抽象层了。
Protocol_Layer Abstraction
// Protocol_Layer abstraction has been defined to decouple the
// different protocol layers. Now the layers only depend upon
// this abstraction.
class Protocol_Layer
{
// Each layer can associate with an upper and lower layer.
// This association is also in terms of the Protocol_Layer
// class. Thus there is no dependency on the actual types
// of individual layers. The only requirement is that they
// should inherit from Protocol_Layer.
Protocol_Layer *m_p_Lower_Layer;
Protocol_Layer *m_p_Upper_Layer;
// Each inheriting layer must override the following methods.
// These methods handle the actual protocol processing.
virtual void Process_Transmit(Datagram *p_Datagram) = 0;
virtual void Process_Receive(Datagram *p_Datagram) = 0;
public:
// Create a protocol layer with the associated upper and
// lower layers.
Protocol_Layer(Protocol_Layer *p_Lower_Layer,
Protocol_Layer *p_Upper_Layer)
{
m_p_Lower_Layer = p_Lower_Layer;
m_p_Upper_Layer = p_Upper_Layer;
}
// Process and transmit the datagram passed by higher layer.
void Transmit(Datagram *p_Datagram)
{
Process_Transmit(p_Datagram);
if (m_p_Lower_Layer)
{
m_p_Lower_Layer->Transmit(p_Datagram);
}
}
// Receive handler for a datagram received from lower layer
void Handle_Receive(Datagram *p_Datagram)
{
Process_Receive(p_Datagram);
if (m_p_Upper_Layer)
{
m_p_Upper_Layer->Handle_Receive(p_Datagram);
}
}
};
class RLC_Physical_Layer : public Protocol_Layer
{
void Process_Transmit();
void Process_Receive();
public:
RLC_Physical_Layer(Layer *p_Lower_Layer, Layer *p_Upper_Layer)
: Protocol_Layer(p_Lower_Layer, p_Upper_Layer)
{ }
};
class RLC_Datalink_Layer : public Protocol_Layer
{
void Process_Transmit();
void Process_Receive();
public:
RLC_Datalink_Layer(Layer *p_Lower_Layer, Layer *p_Upper_Layer)
: Protocol_Layer(p_Lower_Layer, p_Upper_Layer)
{ }
};
class RLC_Network_Layer : public Protocol_Layer
{
void Process_Transmit();
void Process_Receive();
public:
RLC_Network_Layer(Layer *p_Lower_Layer, Layer *p_Upper_Layer)
: Protocol_Layer(p_Lower_Layer, p_Upper_Layer)
{ }
};
依赖倒置的优点
- 解耦合。
- 灵活度高, 能随意匹配和融合各层。
- 可以在层与层之间任意插入一个新的功能层。