2

将参数传递给函数以选择函数的功能的名称是什么?

例如:

enum {
   DoSomething,
   ...
};
void f(FunctionType a);

f(DoSomething);
....
f(DoSomethingElse);

对比:

void DoSomething();
....
void DoSomethingElse();
4

8 回答 8

4

一般来说,可以将其视为一种反模式,因为单独的方法更简单、更明确。但是,某些情况可能会改变这种观点。两个例子:

前控制器

所有Front Controller模式都是这样工作的(Struts 或更高版本):调用一个集中的方法,带有参数;它稍后被分派到正确的处理程序(由参数之一标识)。这里的重点是在许多特定代码之前(和之后,可能是例外)应用一个通用代码。

问题不在于执行这种类型的代码,而在于将其包含在您自己的代码中。如果它在框架代码中(已经编写,经过良好测试等),那很好。例子是所有的拦截技术,比如 Spring ..

命令

Command模式可能非常接近:

  1. 标识符可以识别要执行的命令;
  2. 然后您找到正确的代码:在命令模式中,它是一个对象,因此您可以使用映射找到与标识符对应的对象
  3. 执行代码:在命令模式中,所有这些对象都有一个共同的方法,所以调用它是通用的,不需要切换。
于 2009-09-30T14:37:41.627 回答
3

像这样的结构通常与遍历所有值的循环一起出现。在这种情况下,它是一种伪装的循环切换模式

但这本身并不是反模式。如果您事先不知道参数,那么这样的设计可能是有效的。

于 2009-09-30T14:16:17.540 回答
3

我已将您传入的参数称为“动作”或“动词”。我还没有看到这被命名为模式。您没有展示的是不可避免的switch陈述,这就是 - 我假设 - 为什么您将其称为反模式。

您可以认为它是命令模式的错误实现。维基百科有一篇关于函数对象的文章,这也是一个糟糕的实现。

在面向对象的语言盛行之前,我们做了这样的事情来将函数分组到对象中,并且通常称之为“调度”。(此名称已被包含在模式世界中,并具有不同的含义。)

于 2009-09-30T14:29:59.423 回答
2

控制耦合

我是在 Jim Weirich 的演讲中听说的。通常,该方法将具有一个“标志”参数,用于控制要使用的算法。

请参阅我在Grand Unified Theory of Software Design 的笔记(附有一些参考资料)。

于 2009-10-01T02:05:40.270 回答
1

它不一定是反模式!

即使 f() 函数是一个大开关,它也可以是处理特定“语言”的单个“标记/动词/指令/原子”(或者更确切地说是“发送处理”)的方便位置。此外,f() 函数还可以引入逻辑来决定如何根据运行时上下文调度特定动词。这种以简单、集中的方式将文本/数据动词后期绑定到特定方法的能力很重要,即使在其他情况下,使用 OO 语言的多态和内省特性来服务于该目的可能更合适。

编辑:请参阅 KLE 的回应,因为它呼应了这是一种模式的想法。KLE 还提供了对相同/相似的 Command 和 Front Controller 模式的参考。

于 2009-09-30T14:38:25.803 回答
0

这将成为重构的目标,通过为每种情况创建单独的方法名称并将任何通用代码放入常用方法中。

于 2009-09-30T14:30:35.697 回答
0

我称它为 Dispatcher,因为它可能会根据参数调用更具体的代码。

过于笼统的功能可能是不好的:难以使用、难以维护、难以调试。它们过于笼统的性质使得很难断言前置条件和后置条件以及不变量。尽管如此,Dispatchers 确实有其偶尔的用途。这是提供可扩展性的一种方式——有时它是一种比传统模式更实用的方式。

于 2009-09-30T16:04:34.107 回答
0

这个例子可以被认为是一个过早的概括

额外参数。只有一种情况是添加参数构成函数或类主体的泛化:如果此参数是“活动的”(作为对象或类型或函数指针),并且函数或类如何工作的一些特殊细节会移动到此参数表示的代码。这些示例是排序函数的排序谓词参数和容器类模板或构造函数的分配器参数。仅当此代码不关心此参数的实际值时,附加参数才可能构成调用函数或使用类的代码的概括。

编码

  enum command{ start, stop };
  void f_command(command do){
    if( do==start )
        f_start();
    else
        f_stop();
  }
  void f(){
    f_command(start);
    f_command(stop);
  }

VS

  void f(){
    f_start();
    f_stop();
  }
于 2012-06-08T14:09:57.453 回答