对于多个方法(所有方法都接受不同的派生类作为参数),正确的 C# 设计模式是什么?
我有一个基类:
class Message
和两个派生类:
class SimpleMessage : Message
class ComplexMesssage : Message
这些类型在代码的另一部分中使用,如下所示:
void ProcessSimpleMessage(SimpleMessage m)
void ProcessComplexMessage(ComplexMessage m)
这些方法不在 Message 类内部,因为处理不是消息的一部分。
现在,我想避免使用 if/else/switch 结构,因为消息有很多类型。这里使用的最佳设计模式是什么?
一种选择是使用策略模式进行封装(至少按照我的理解):
class ProcessableMessage
{
delegate void ProcessMessageDelegate(Message m)
private Message m;
private ProcessMessageDelegate ProcessMessage;
}
但是让所有处理方法接受基本类型 Message 并在内部进行强制转换真的是最佳实践吗? 另一个问题是消息的动态类型(简单或复杂)实际上存储在此类中的两个位置 - 消息和处理算法,这看起来有点丑陋。
还有更好的解决方案吗?
谢谢!!
阿萨夫
I have a base class:
class Message
And two deriving classes:
class SimpleMessage : Message
class ComplexMesssage : Message
These types are used in another part of the code as such:
void ProcessSimpleMessage(SimpleMessage m)
void ProcessComplexMessage(ComplexMessage m)
These methods are not inside the class Message, as the processing is not part of the message.
Now, i would like to avoid an if/else/switch structure, because there are many types of messages. What is the best design pattern to use here?
One option is to encapsulate using the strategy pattern (at least as i understand it):
class ProcessableMessage
{
delegate void ProcessMessageDelegate(Message m)
private Message m;
private ProcessMessageDelegate ProcessMessage;
}
But is it really best practice to make all the processing methods accept the base type Message, and cast inside?
And another problem would be with the fact that the dynamic type of the message (simple or complex) is actually stored in 2 places in this class - the message and the process algorithm, which seems kind of ugly.
Any better solutions out there?
Thanks!!
Assaf
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我会在这里使用访客模式:
I'd use the visitor pattern here:
为什么不直接添加虚拟方法:
如果您确实需要将代码分开:
我的意思是,我们这里需要什么样的灵活性?还涉及哪些其他类别?您周围的场景是什么?在没有任何其他上下文的情况下,这确实是最容易理解、也最容易实现的方法。有时,人们会在确实不需要的时候添加一些设计缺陷。
策略模式通常适用于如果您希望使用不同的方法来处理相同的消息类型,并希望在运行时切换它们。如果一种类型的处理通常与一种类型的消息一起使用,那么您不需要使其变得更加复杂。
Why not just add the virtual method:
If you really need to keep the code separated:
I mean, what sort of flexibility do we need here? What other classes are involved? What is your surrounding scenario? Without any other context, this is really the simplest method to understand, and easiest to implement. Sometimes people add design cruft when it really isn't needed.
The strategy pattern is generally for if you wanted to have different methods to process the same message type, and wanted to switch them at runtime. If one type of processing generally goes with one type of message, then you don't need to make it any more complicated.
我喜欢上面的访客方法。不过,只是为了好玩,我展示了如何在 VS2008 和 VS2010 中使用 T4 减少代码冗余。
冗余来自于每条消息都需要一个 Visit 方法。此外,每个方法都需要一个简单但冗余的 Accept 实现。更接近“不要重复自己”的一种方法是使用 T4 生成代码。
为了测试以下示例,请在 VS 中添加一个类,但将扩展名从 .cs 更改为 .tt。您现在将获得两个文件:.tt 文件和连接到 .tt 文件的 .cs 文件。
.tt 文件是生成.cs 文件的模板。当时它们是相同的。
使用它作为 .tt 文件的内容:
这应该生成一个如下所示的 CS 文件:
为什么这不那么冗余?因为现在每当我想添加新消息时,我只需将其添加到模板中:
需要注意的是,所有消息都是部分生成的,因为我们需要不同的消息负载。这是在另一个文件中指定的,它可能如下所示:
对于那些喜欢 T4 声音的人,请查看此博客:http://www.olegsych.com/2008/09/t4-tutorial-creatating-your-first-code-generator/
I like the Visitor approach above. However just for the fun of it I show a bit on how to reduce redundancy in code using T4 in VS2008 and VS2010.
The redundancy comes from that for each message you need a Visit method. Also each method needs a simple but redundant implementation of Accept. One way to get closer to "Do not repeat yourself" is generating the code using T4.
In order to test the following sample add a class in VS but change the extension from .cs to .tt. You will now get two files a .tt file and a .cs file connected to the .tt file.
The .tt file is a template that generates .cs file. At the time they are identical.
Use this as the content for the .tt file:
This should generate a CS file that looks like this:
Why is this less redudant? Because now whenever I like to add a new meessage I just add it to the template:
It's important to note that all messages are generated as partial because we need different payloads for a message. This is specified in another file and it could look like this:
For those that likes the sound of T4 check this blog: http://www.olegsych.com/2008/09/t4-tutorial-creatating-your-first-code-generator/