1

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

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

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

认为这应该可行。

4

4 回答 4

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

于 2009-05-02T16:42:21.600 回答
1

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

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

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

于 2009-05-02T16:54:26.233 回答
0

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

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

于 2009-05-02T16:44:01.110 回答
0

你可以这样做:

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

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

于 2009-05-02T16:50:04.480 回答