如何根据消息类型处理不同的处理?

时间:2009-05-02 16:38:01

标签: design-patterns oop observer-pattern

我有一个进程,它有一个“notify”方法,它接收消息类型的基类作为参数。我想根据派生的消息类型进行不同的处理。这是否意味着我需要添加一个名为“process”的方法或类似于消息类型的方法,并使用多态来调用它?为每种特定的消息类型添加“通知”更好吗?

更多细节:语言是C ++。我认为通知在这里是一个好主意,所以我只需要一种方法来通知各种消息类型。控制器继承自一个监听器类,该类指定一个纯粹的虚拟通知(MsgBaseClass)方法。我仍然喜欢这个想法,因为我不必为每个新消息类型添加通知。但是在控制器代码本身中,我没有看到任何方法来区分消息类型而不是动态强制转换或向消息添加消息类型。

编辑:我想我会选择访客模式。它允许我只保留一个通知方法,我可以避免在我的代码中使用switch语句。 “访问者”接口将指定侦听器处理各种派生消息类型所需的各种方法。这将只需要将一条消息添加到Message基类,一个纯虚拟的“accept(MyMessageTypeVisitor v)。派生的消息类将使用v.visit(this)实现它;

认为这项工作非常重要。

4 个答案:

答案 0 :(得分:1)

编辑:我认为dirkgently有一个好点,而且消息不应该知道如何处理自己。因此,我所描述的消息可以用作工厂的方法并不是一个好主意。我确实认为抽象流程工厂可能是一个很好的解决方案。

使用抽象工厂创建一个可以处理处理的对象,并使用多态来调用它。此工厂可能直接包含在消息类中,或者您可以创建一个单独的工厂类,它接受消息类型作为参数并返回适当的对象。

class Message {
public:
  virtual Processor *getProcessor() = 0;
  // other methods
};

class Processor {
public:
  virtual void doWork() = 0;
};

class MyListener : Listener {
public:
  void notify(Message *message);
};

void MyListener::notify(Message *message) {
  Processor *proc = message->getProcessor();
  proc->doWork();
};

(对不起,如果这是不正确的。我的C ++有点弱,但我相信它说明了原理。)

这将允许您为每种消息类型覆盖getProcessor(),并在那里创建适当的处理器。

IMVHO,Polymorphism是要走的路。我猜你想要做的那种处理逻辑不属于消息类,应该移到单独的类中。我更喜欢这种方法的另一个原因是,如果我添加其他消息,它不需要我更改被通知的类的结构。如果只有一种或两种消息类型,这可能不是问题。

答案 1 :(得分:1)

经典的OO答案要求基本消息类提供一个抽象方法,具体消息子类重写该方法以提供特定处理。

Dylan和CLisp等一些(不是非常普遍的)语言提供了“泛型函数”(在参数类型上动态调度),可以非常彻底地解决问题。

流行语言中可行的一种灵活方法是Uncle Bob的“非循环访问者”设计模式,http://www.objectmentor.com/resources/articles/acv.pdf;有关更多访客变体,请访问www.ccs.neu.edu/research/demeter/adaptive-patterns/visitor-usage/papers/plop96/variations-visitor-nordberg.ps。

答案 2 :(得分:0)

您是否坚持使用观察者设计模式?

重载notify看起来像候选人。观察者模式非常简单。它基于the Hollywood Principle,即“不要打电话给我们,我们会打电话给你!”。我们的想法是拥有一组对象(观察者)并通知他们,而不是让他们查询你。您将一般Event种数据传递给观察者。它应由观察者决定如何处理。如果观察者对不同事件做出反应,那么会有一些dynamic_casts(是的,你也需要一个事件层次结构)。

答案 3 :(得分:0)

你可以这样做:

DerivedType *dt = dynamic_cast< DerivedType >( &BaseType );
if( dt != NULL )
{
    // Handle processing of DerivedType
}

尝试对每个处理过的DerivedType执行dynamic_cast。如果你得到一个非空指针,那么你知道你已经收到了你试图转换的类型。