加载多种消息类型的设计模式 [英] Design pattern for loading multiple message types

查看:176
本文介绍了加载多种消息类型的设计模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在浏览SO时遇到一个有关处理多个消息的问题类型。我担心的是-如何以一种简洁的方式加载此类消息?我决定使用一个方法单独的类,该方法每次调用都会加载一条消息。此方法应创建一个具体消息类型的新实例(例如AlphaMessage,BetaMessage,GammaMessage等),并将其作为消息返回。

As I was looking through SO I came across a question about handling multiple message types. My concern is - how do I load such a message in a neat way? I decided to have a separate class with a method which loads one message each time it's invoked. This method should create a new instance of a concrete message type (say AlphaMessage, BetaMessage, GammaMessage, etc.) and return it as a Message.

class MessageLoader
{
    public Message Load()
    {
        // ...
    }
}

该方法中的代码对我来说真的很糟糕,我非常想对其进行重构/摆脱它:

The code inside the method is something which looks really awful to me and I would very much like to refactor it/get rid of it:

Message msg = Message.Load(...); // load yourself from whatever source
if (msg.Type == MessageType.Alpha) return new AlphaMessage(msg);
if (msg.Type == MessageType.Beta) return new BetaMessage(msg);
// ...

实际上,如果整个设计看起来太凌乱并且你们有更好的解决方案,我已经准备好对整个事情进行重组。

In fact, if the whole design looks just too messy and you guys have a better solution, I'm ready to restructure the whole thing.

如果我的描述太混乱了,请告诉我它丢失了什么,我将进行编辑问题。谢谢大家。

If my description is too chaotic, please let me know what it's missing and I shall edit the question. Thank you all.

编辑:
我对这段代码不满意的是,我必须创建一个实例。一条消息(因为它知道如何加载自身),然后必须用一种具体的消息类型来修饰它(因为装饰者知道如何解释msg的Data属性)。

What I don't like about this code is that I have to create an instance of a Message (cause it knows how to load itself) and then have to decorate it with a concrete message type (cause decorators know how to interpret msg's Data property). Maybe this will make the question slightly more clear.

推荐答案

下一个抽象层次是使消息发现和实例化动态化。这通常是通过将字符串名称与每个消息相关联或通过使用类的名称作为标识符来实现的。您可以使用反射来发现可用的消息类型,将它们存储在字典中并按名称提供实例化。可以进一步扩展它,以从动态加载的插件程序集中引入消息,并带有适当的元数据和接口,以允许不同消息和消息使用者之间的松散耦合组合。一旦达到该级别,我建议您研究诸如 MEF 之类的框架,这些框架可以自动执行发现和实例注入过程。

The next level of abstraction is to make Message discovery and instantiation dynamic. This is often accomplished by associating a string name with each Message or by using the name of the class as an identifier. You can use Reflection to discover available Message types, store them in a Dictionary and provide instantiation by name. This can be further extended to bring in Messages from dynamically loaded 'plugin' assemblies, with appropriate meta-data and interfaces to allow for loosely coupled composition between different Messages and Message Consumers. Once you get to that level, I recommend looking into frameworks like MEF which automate the discovery and instance injection process.

对于您的简单应用程序,我认为您的方法已经很干净了。只要您有一组相对较小且稳定的案例,一系列的if语句或switch就能很好地工作并且易于理解/维护。

For your simple application, I think your approach is already quite clean. A series of if statements or a switch works just fine and is easy to understand/maintain, as long as you have a relatively small and stable set of cases.

总结评论中的进一步讨论:

Summarizing the further discussion in the comments:

主要的设计问题是产生不安,这是因为不同的特定消息是从Message和但是,在更具体的消息可以执行进一步分析之前,必须实例化基本消息。这混淆了消息是打算包含原始信息还是充当已解释消息的基本类型。更好的设计是将RawMessage功能分离到其自己的类中,从而清楚地将关注点分离并解决实例化两次的感觉。

The main design concern creating uneasiness was the fact that the different specific messages inherited from Message and yet a base Message had to be instantiated before the more specific messages could perform further analysis. This muddied up whether the Message is intended to contain raw information or to act as a base type for interpreted messages. A better design is to separate the RawMessage functionality into its own class, clearly separating concerns and resolving the feeling of 'instantiating twice'.

使用DTO和映射器进行重构类:

As for refactoring with DTOs and a mapper class:

我实际上更喜欢您的应用程序特定消息编码/解码的方法。如果我想查找为什么FactoryTakenOverByRobotsMessage包含无效数据的原因,则对我来说有意义的是,消息的解析器方法包含在消息的解码数据中。如果您想支持不同的编码,那么事情会变得更加复杂,现在您开始希望声明性地指定DTO(例如,带有属性),并允许您的不同传输层决定如何序列化/反序列化。但是,在大多数情况下,当我使用您的模式时,这是针对特定于应用程序的情况,消息格式有时会有些不一致,并且各种专有编码无法以任何自动方式很好地映射。我仍然可以始终将声明性编码与专有的类内编码并行使用,并进行诸如将消息序列化为XML进行调试的操作。

I actually prefer your approach for an app-specific message encoding/decoding. If I want to track down why FactoryTakenOverByRobotsMessage contains invalid data, it makes sense to me that the parser method for the message is contained with the decoded data for the message. Where things get more dicey if when you want to support different encodings, as now you start wanting to specify the DTO declaratively (such as with attributes) and allow your different transport layers to decide how to serialize/deserialize. In most cases where I'm using your pattern, however, it's for a very app-specific case, with often somewhat inconsistent message formats and various proprietary encodings that don't map well in any automatic way. I can always still use the declarative encoding in parallel with the proprietary, in-class encoding and do things like serialize my messages to XML for debugging purposes.

这篇关于加载多种消息类型的设计模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆