在软件开发过程中,网络层往往是以一个能够提供底层服务的角色出现。逻辑层是要依赖于网络层的,网络层是为逻辑层提供服务的。对于逻辑层来说,它不需要知道网络层中的具体实现,不需要知道网络层的具体对象名称;对于网络层来说,它不需要知道逻辑层中的设计。层与层之间要实现解耦合,只要网络层和逻辑层之间能够有一套契约存在,然后各自实现对契约中规定的接口编程,那么就算将来网络底层发生变动也不会影响到逻辑层的代码。
为了实现这样的效果,用一个简单的C++代码例子来说明。
假设网络层有个类CNetwork,逻辑层有个类CLogical,它们之间的契约用一个interface接口名叫INetwork。
从调用者的角度来看,创建过程理想中应该是这样的。
CNetwork* pNetwork = new CNetwork();
CLogical* pLogical = new CLogical( (INetwork*)pNetwork );
先创建网络,再创建逻辑,逻辑要依赖于网络。当然这是理想中的,之后再来实现它。
接下来该设计它们之间契约的内容了。为了能简单说明问题,这里就只考虑网络收发的接口怎么设计了。发送可以由逻辑层直接来调用,接受可以通过回调函数由网络层主动通知逻辑层(当然网络不需要知道逻辑的设计,一切就契约来实现)。契约可以是这样的:
typedef void (*RecvFunc)(WPARAM wParam, LPARAM lParam);
interface INetwork
{
virtual void SendNetMessage(WPARAM wParam, LPARAM lParam) = 0;//网络发送
virtual void SetRecvCallBack(RecvFunc pFunc) = 0;//用来设置回调函数
};
现在可以来实现理想中的调用方法了,在CLogical中应该有一个INetwork的接口指针
class CLogical
{
public:
CLogical(INetwork* pNetwork);
virtual ~CLogical();
static void RecvProc(WPARAM wParam, LPARAM lParam);
private:
INetwork* m_pNetwork;
};
构造函数中来初始化接口指针,并且把回调函数的函数指针告诉网络层。
CLogical::CLogical(INetwork* pNetwork) :m_pNetwork(pNetwork)
{
m_pNetwork->SetRecvCallBack(RecvProc);// 设置回调函数
}
void CLogical::RecvProc(WPARAM wParam, LPARAM lParam)
{
// 这里就等着网络层把收到的数据发过来吧~!
}
当然网络层的指责就是遵守INetwork契约来实现功能咯……因此CNetwork应该是继承于INetwork。如下:
.h
class CNetwork :public INetwork
{
public:
CNetwork();
virtual ~CNetwork();
virtual void SendNetMessage(WPARAM wParam, LPARAM lParam);//网络发送功能
virtual void SetRecvCallBack(RecvFunc pFunc);// 让调用者设置回调函数
private:
// ……
private:
RecvFunc m_pFunc;// 调用者回调函数的指针,通过它就可以把网络层接收到的数据发送给逻辑层。
};
逻辑层始终是通过INetwork接口来使用网络的,网络对它来说是隐藏的,不知道网络的任何其它细节;网络层负责遵守INetwork契约来实现功能。这样两者就真正解藕了。