6

什么是(如果有的话)隐含的假设或限制以及设计的差异,例如:

在他的:

class SampleClass1
{
    IWorker workerA;
    IWorker workerB;

    void setWorkerA(IWorker w);
    void setWorkerB(IWorker w);
    WorkResult doWork();
}

B)与此相比:

class SampleClass2
{
    WorkResult doWork(IWorker workerA, IWorker workerB);
}

我知道这取决于具体的项目,但是如果上面的类是一个小框架的一部分呢?第一类能够更自然地维护状态并分离步骤,但第二类确保与外部调用者更自然的“实时通信”,因为每次调用 doWork() 时都会传递 Worker。

是否有任何推荐的用法或通用做法来指导上述两种方式之间的选择?谢谢。

4

8 回答 8

6

样本类 1

  • 我可能需要在 doWork 之间保持工人的状态
  • 我可能需要单独设置工人的能力。(使用 1 和 2,然后使用 2 和 3)
  • 我想维护工人,因为它可能会在同一个工人上运行 doWork 多次。
  • 我不是实用类。我的一个例子很重要。

样本类 2

  • 给我两个工人,我会和他们一起工作。
  • 我不在乎他们是谁,我也不想维护他们。
  • 维持工人之间的任何配对都是别人的工作。
  • 我可能更像是一个实用类。也许我可以只是静止的。
于 2008-09-26T09:10:57.980 回答
5

在选项 (A) 中,您正在创建所谓的 Function Object 或 Functor,这是一种有据可查的设计模式。

两个主要优点是:

  • 工人可以在一个地方设置,然后在其他地方使用对象
  • 对象可以在调用之间保持状态

此外,如果您使用依赖注入框架(Spring、Guice 等),则可以在任何需要的地方自动初始化和注入仿函数。

函数对象广泛用于库中,例如 C++ 标准模板库

于 2008-09-26T09:26:48.753 回答
2

另一种选择是案例 A 的变体,如下所示:

类 SampleClass3
{
    SampleClass3(IWorker workerA, IWorker workerB);
    工作结果 doWork();
}

好处:

  • 使对象有缺陷更难,因为您需要提供施工时所需的所有工人(与案例 A 相比)。

  • 您仍然可以在 SampleClass3 和/或其中一名工作人员中携带状态。(在情况 B 中这是不可能的。)

缺点:

  • 在构建 SampleClass3 之前,您必须准备好所有工作人员,而不是稍后再提供。当然,您也可以提供设置器,以便以后更改它们。
于 2008-09-26T10:01:12.930 回答
1

如果不止一种方法依赖于 IWorker a 和 IWorker b,我说做样本 A。

如果只有 doWork() 同时使用了 IWorker a 和 IWorker b,则执行示例 B。

另外,您的 SampleClass 的真正目的是什么?doWork 看起来有点像实用方法 mroe。

于 2008-09-26T09:05:58.430 回答
1

A) 是一个糟糕的设计,因为它允许对象有缺陷(可能没有设置一个或两个工作类)。

B) 可以很好。如果您不依赖 SampleClass2 的内部状态,请将其设为静态

于 2008-09-26T09:08:22.497 回答
0

另外一个选项:

IWorker 类:

静态 WorkResult doWork(Iworker a, Iworker b);

于 2008-09-26T09:03:22.913 回答
0

IMO 第二种方法看起来更好,它要求调用者使用更少的代码来执行任务。第二种方法不太容易出错,调用者不必担心对象可能没有完全初始化。

于 2008-09-26T09:08:37.690 回答
0

不如定义一个简单地返回 a并让各个类决定它们如何实现它的WorkDelegate(或者具有一个没有参数的单个方法的接口)呢?这样,您就不会局限于过早的决定。doWorkWorkResult

于 2008-09-26T09:08:47.863 回答