Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我应该在这里使用哪种设计模式_C#_Design Patterns - Fatal编程技术网

C# 我应该在这里使用哪种设计模式

C# 我应该在这里使用哪种设计模式,c#,design-patterns,C#,Design Patterns,出于学习目的,我正在编写一个基于套接字的客户机/服务器应用程序。我设计了一个自定义协议,以确保我能够正确处理数据包。今天在检查代码的一些旧部分时,我意识到我创建数据包的方法包含了很多冗余代码 我有不同类型的数据包,例如ImagePacket、MessagePacket等。所有类型的创建仅在次要内容上有所不同,例如,头和分隔符的创建是相同的 为了改进这一点,我提出了如下解决方案(简化): AddData方法作为抽象方法实现,并在具体类中重写,而AddHeader和AddDelimiter则在抽象类

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

我有不同类型的数据包,例如ImagePacket、MessagePacket等。所有类型的创建仅在次要内容上有所不同,例如,头和分隔符的创建是相同的

为了改进这一点,我提出了如下解决方案(简化):

AddData方法作为抽象方法实现,并在具体类中重写,而AddHeader和AddDelimiter则在抽象类包本身中定义

这工作得很好,我没有以前那么多重复的代码,但我不满意 将对象传递给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()
-这将保留您的代码Ruby on Rails使用验证来解决此问题


如果您的addData()函数在输入上调用了validate(),那么您只需在每个子类中重写validate()。

我将转到返回接口的工厂模式


除此之外,您不需要将ref用于引用类型。

我认为您当前的解决方案还可以。您只需将传递给
ImagePacket
构造函数的数据类型缩小为
Image
类型。例如:

class ImagePacket : Packet{
  public ImagePacket(Image img) : base(img){}
}

这将在复印时检查数据是否为图像。当然,如果您确实必须传递一个
对象
类型,那么这可能不起作用。

问题在于数据参数可以是什么。用户想知道数据可以是字符串还是图像。也许我应该更清楚一些,但当然,它可以-我会有很多重载,采用不同的数据类型,可能还有一个额外的
enum
类型用于字符串数据
class ImagePacket : Packet{
  public ImagePacket(Image img) : base(img){}
}