c ++设计模式,用于将对象流的转换链接在一起

时间:2011-12-15 16:29:44

标签: c++ design-patterns

我正在研究一个多线程库,它监视来自winpcap的网络流量,并将数据包转换为几种不同类型的数据结构,供各种应用程序使用。

对于每种类型的输出,将需要几个转换,每个转换可以被描述为采用类型X的0-N对象,然后生成0-N类型的Y,然后将在下一步中使用这个过程。

重要的是要注意在X转换为Y的过程中。如果我们目前只有5个(例如)X,那可能会或可能不足以创建Y,或者它可能足以创建许多Y,具体取决于转换和收到的数据。

为了保持一致,我们显然希望为每个转换对象使用标准模式。我希望有人可以指出一个常用的模式,希望依赖于std(或boost)库。

另外,我们一直在讨论使用继承链将不同层链接在一起的可能性。

IE。

class ProcessXtoY: ProcessWtoX
{
    void processData(iterator<X> begin, iterator<X> end)
    {
        /* create Y's, send output to  */
    }
    virtual void processData(iterator<Y> begin, iterator<Y> end) = 0;
}

class ProcessYtoZ: ProcessXtoY
{
    void processData(iterator<Y> begin, iterator<Y> end)
    {
        /* ... */
    }
}

有人可以为这类项目提出一些常用模式的例子吗?

3 个答案:

答案 0 :(得分:2)

使用继承将转换链接在一起不是应该使用的继承,而是在添加新转换时非常不灵活。如果您需要新的转换组合(例如W直接转换为Y)。

相反,您是否考虑过创建描述每个转换算法的转换类,然后使用std :: transform并将转换链接在一起?

答案 1 :(得分:1)

您的示例中的方法(我称之为&#34;迭代&#34;方法)是一个明显的稻草人 - 您正在推动无限的数据包流,因此没有结束()他们。

我认为你可以采用拉动或推动方法。对于拉,这是Java的一些东西 hasNext()/下一个()。不幸的是,它很难分支,原始数据源需要排队,因为我们不知道消费者什么时候会收拾口袋。

对于推送方法,您可以使用register(listener)和listener.process()组合。这个很容易分支,并且系统可以为您完成缓冲(如果网络数据包层的进程()(需要太长时间),或者您可以在任何级别引入显式队列。

总的来说,我在这里推荐事件听众。

答案 2 :(得分:1)

我有一些建议。您可以使用Decorator Pattern的变体。您可以修改此模式,以便将不同的对象类型链接在一起。然后,如果您对同一转换有不同的实现,则很容易出问题,或者在运行时将其淹没。可能有一个模式,已经命名,某个地方是这个变种,但你应该能够从装饰模式的基础知识中派生它。

如果您需要多线程解决方案,我建议您通过生产者/消费者队列将转换链接在一起(请参阅this)。这样你实际上可以让几个不同的消费者(变换)并行工作,并将完成的变换放到行中的下一个生产者/消费者身上。当然,这实际上只有在您的变换的排序与您的程序的其余部分无关紧要时才有效,或者您有一些方法可以跟踪它并在最终对象再次需要时重新排序。同样,如果你有不同的实现方式,你可以以编程方式或在运行时轻松交换转换。

如果您需要更通用且可配置的东西,您可以使用Builder Pattern来封装链接过程并允许构建器的完整运行时配置,并且可以更好地控制交换链接过程。当然,您可以在构建器中使用其他模式来实现转换链。