出于学习目的,我正在编写基于套接字的客户端/服务器应用程序。我设计了一个自定义协议,以确保可以正确处理我的数据包。今天,在检查一些较旧的代码部分时,我意识到我创建数据包的方式包含很多冗余代码。

我有不同类型的数据包,例如ImagePacket,MessagePacket等。所有类型的创建仅在次要方面有所不同,例如标头和定界符的创建是相同的。

为了改善这一点,我想出了这样的解决方案(简化):

abstract class Packet
{
 public Packet(object o)
 {
 MemoryStream memoryStream = new MemoryStream();

 AddHeader(ref memoryStream);
 AddData(ref memoryStream, obj);
 AddDelimiter(ref memoryStream);
 _packetBytes = memoryStream.ToArray();

 memoryStream.Close();
}
protected abstract void AddData(ref MemoryStream ms, object obj);


AddData方法作为抽象方法实现,并在具体的类中覆盖,而AddHeader和AddDelimiter在抽象类Packet本身中定义。

这可以正常工作,我没有像以前那样重复的代码,但是我不满意
将对象传递给AddData,因为目前尚不清楚我不能给ImagePacket构造函数一个字符串。

// correct
Packet myMsgPacket = new MessagePacket("hello world");
Packet myImagePacket = new ImagePacket(image);
// wrong, but will be compiled :(
Packet myChaosPacket = new ImagePacket("muaha you're doomed");


如果必须对传递的正确数据类型进行检查,那么我将再次得到大量的愚蠢代码。
如何减少重复的代码,又能摆脱上述问题?

最佳答案

听起来您需要使用工厂模式

Packet MyPacket = MyPacketFactory.CreatePacket(Data)


然后MyFactory.CreatePacket将返回IPacket

更新:根据下面的评论,我应该更清楚了。您的工厂可以有许多重载的CreatePacket()方法,这些方法采用不同的数据类型...

IPacket CreatePacket(Image Data) {}
IPacket CreatePacket(String Data) {}
IPacket CreatePacket(Exception Data) {}


并且如果您有多种仅包含字符串的数据包类型(例如消息包,状态包或类似包),则可以创建一个枚举,指示需要哪个字符串包...

IPacket CreatePacket(String Data, StringPacketTypesEnum PacketType) {}


在数据包工厂内部,您可以具有处理所有重复代码的通用功能-例如AddDelimiter()-这将使您的代码保持DRY

关于c# - 我应该在这里使用哪种设计模式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4481483/

10-10 23:41