Template method pattern是GOF24种设计模式中的一种即名”模板方法模式”,意图即为”定义一个算法的骨架, 将具体的算法实现延迟到子类中实现。”
在M4.3多线路服务端的预研开发中,服务端主要实现一个连接代理转发数据的功能,但是连接的种类繁多。有多线路自身的命令隧道,数据传输隧道,应用层代理连接。每一种隧道的数据读取方式都是相同的,都是利用环形缓冲区空间去readv某个socket.而不同点在于每次read后得到的数据处理。同理,连接发送数据,关闭连接等都可能会因为具体的socket类型不同而不同,但是基本的操作顺序还是不变的。比如close, 但是先清理掉发送和接收缓存然后关闭fd。但是应用层连接在关闭前需要实时通知客户端应用层也相应关闭,所以应用层连接的close需要在以上步骤之前插入一个关闭消息的发送。
类结构图:
class CTcpSocket { public: CTcpSocket(int); //构造函数 virtual ~CTcpSocket(); //析构函数,为virtual表明需要被继承 int AllocateRecBuffer(int); //分配接收缓冲区大小 int AllocateSendBuffer(int); //分配发送缓冲区大小 CBuffer* GetRecvBuffer() const; //获取接收缓冲区指针 CBuffer* GetSendBuffer() const; //获取发送缓冲区指针 int SendMix(char*, int); //传入buffer,和发送缓冲区剩余 int SendMix(struct iovec*, int); //传入vec,和发送缓冲区剩余发送 void Close(); //关闭该Sockets bool Equals(int ) const; //判断一个fd和该类的fd是否相等 int Nirvana(int); //重新使用该类 unsigned int GetLocalIp() const; //获取该类的fd的本地ip地址 int GetFd() const; //获取fd值 CUser* GetUser(); //获取该fd所分配的CUser类 void Read(); //该类的读事件 void Write(); //该类的写事件 void SendVec(struct iovec*, int); //传入vec,一起发送并处理返回值 protected: CTcpSocket(const CTcpSocket&); //禁止拷贝构造 CTcpSocket& operator = (const CTcpSocket&); //禁止赋值 virtual void _DoSendData(); //子类实现具体的读取数据后的发送 virtual void _DoWrite(); //子类实现具体的发送缓冲区代码 virtual void _DoClose(); //子类实现具体的fd关闭的相关清理 int _Writenv(struct iovec*, int ); private: int m_iFd; unsigned int m_uiLocalIp; CBuffer* m_pSendBuffer; CBuffer* m_pRecvBuffer; }; class CTcpCommand : public CTcpSocket { public: CTcpCommand(int); ~CTcpCommand(); void SendMessage(unsigned int); //供外部发送命令隧道消息接口 protected: CTcpCommand(const CTcpCommand&); CTcpCommand& operator = (const CTcpCommand&); void _DoReplyCreateAck(unsigned int); //回复隧道建立 void _CloseTunnel(int); //关闭应用层隧道 void _DoLineDetect(unsigned int); //回复线路探测 void _DoSendData(); //TcpCommand的读取数据处理 void _DoWrite(); //发送缓冲区剩余数据 void _DoClose(); //fd关闭前的相关处理 }; class CTcpDataTrans : public CTcpSocket { public: CTcpDataTrans(int); ~CTcpDataTrans(); protected: CTcpDataTrans(const CTcpDataTrans&); CTcpDataTrans& operator = (const CTcpDataTrans&); void _DoSendData(); //TcpDataTrans的读取数据处理 void _DoWrite(); //发送缓冲区剩余数据 void _DoClose(); //fd关闭前的相关处理 }; class CTcpTunnel : public CTcpSocket { public: CTcpTunnel(int); ~CTcpTunnel(); protected: CTcpTunnel(const CTcpTunnel&); CTcpTunnel& operator = (const CTcpTunnel&); void _DoSendData(); //TcpTunnel的读取数据处理 void _DoWrite(); //发送缓冲区剩余数据 void _DoClose(); //fd关闭前的相关处理 }; 主要的三个处理都是隐藏在_DoSendData(), _DoWrite(), _DoClose()三个方法中,由各个子类去实现自己的具体处理逻辑。 模板方法模式中牵涉到一些C++惯用法: virtual 函数的特性不受访问权限控制 private: 可override, 也可不override.但是不能调用基类的实现 protected: 子类必须override public: 不建议使用,访问权限越低越好,由private到public容易,由public到private难. (template method pattern的背景下) virtual destroy 函数: 表明这个类需要被继承,同理非virtual destroy表明不能被继承 禁止被外部析构. 声明destrutor不为public, 同理构造,拷贝,赋值 Public继承, is a Private继承, 用什么实现 参考文档: <<Effective C++>> <<C++经典对话>>