【问题标题】:Is this singleton design pattern bad? Is it wrong to use Singleton in this case?这种单例设计模式不好吗?在这种情况下使用 Singleton 是错误的吗?
【发布时间】:2015-10-17 06:26:34
【问题描述】:

问题:

为简单起见,我将使用一个简单的示例。在示例应用程序中,A 类读取一些数据。

Class-A 然后实例化 Class-B,然后实例化 Class-C。所以总共有一个 3 级层次的类A --> B --> C

B 类根据 A 类中的数据创建和管理自定义对象。我只是以函数/方法参数的形式将该数据从 A 类传递到 B 类。

然而,C 类是不同的。它有 2 个函数/方法为其提供数据。

  1. firstMethod(arg) - 为它提供了可以使用的数据。 (在 B 类上调用)
  2. otherMethod(otherArg) - with 为它提供其他数据。

它被 Class-B 实例化,它需要来自 Class-B 的数据将通过 firstMethod(arg1) 传递给 Class-B 传递给它。但是,还有另一个数据集需要 C 类才能正常运行。这个其他参数与class-B无关;因此,通过这些类将这些信息作为参数传递给 C 类似乎是错误的。

如何在不使用 B 类的情况下从 A 类到 C 类获取此信息? 我所做的是创建一个单例类-S。

Class-S 在其中定义了 class-A 的方法/函数(不是变量)。设置好之后,Class-C 现在可以在 Class-S 上调用它的otherMethod(otherArg),后者调用所需的函数并直接从 A 类返回所需的数据。

A-->B-->C
^       |
|___S___|

问题:

我列出了我在网上看到的单身人士的一些问题。

  1. 来自this link,它们通常用作全局实例,为什么这么糟糕?因为您在代码中隐藏了应用程序的依赖项,而不是通过接口公开它们。使某些东西全局化以避免传递它是一种代码味道。 [我的编辑] - 虽然 class-S 被用作全局实例,但 Class-c 明确定义了它的依赖关系。它工作所需的方法/功能在其接口中定义。
  2. 来自this link,它们本质上会导致代码紧密耦合。在许多情况下,这使得在测试中伪造它们相当困难。 [我的编辑]这个设置是否仍然将 C 类与单例紧密耦合?如果要对 C 类进行单元测试,则不需要单例(至少我不这么认为)。由于函数已明确定义,因此模拟类可以伪造其数据。
  3. 它们在应用程序的整个生命周期内携带状态。测试的另一个打击,因为您最终可能会遇到需要订购测试的情况,这对于单元测试来说是一个很大的禁忌。为什么?因为每个单元测试都应该相互独立。 [我的编辑]鉴于设置我不确定这会是一个问题吗?

对此的任何指示都会有很大帮助。请不要恨..我用谷歌搜索但没有找到很多明确的答案。谢谢。有什么想法吗?

[我的编辑] --> 下面的评论提出了以下我认为很重要的问题,可以在此处添加。

您为什么不想将附加数据传递给 B?如果执行命令[in class-C]需要这个数据,那么它应该是一个参数。不管B是直接使用还是传下去

答案是,这是一个使用 A、B 和 C 的简单示例。事实上,该应用程序要复杂得多。 Class-B 是一个可重用的类,用于应用程序的许多其他部分。如果我让 B 类接受附加数据作为传递给 C 类的参数,那么在使用 B 类的应用程序的所有其他部分中,我必须为该参数传递 nil。此外,如果在应用程序中的更多地方使用 B 类:B->C...B->X...B->Y...B->Z ... 等等,那么可重用的 B 类现在必须携带 C、X、Y 和 Z.. 或更多的参数。 Class-B 是一个可以实例化不同类型的类的类,但它不知道有关它已实例化/分配的类的信息。它的工作只是实例化/分配一个类,通过参数给实例化类它需要的一般信息,最后做一些额外的设置。但是 B 类不应该知道其实例类的其他特定数据。所以它不会知道 C 类需要去 A 类获取它的信息。只有 C 类知道从哪里获取其特定信息。

【问题讨论】:

  • 为什么不想将附加数据传递给B?如果执行命令需要这个数据,那么它应该是一个参数。不管B是直接使用还是传下去。
  • @NicoSchertler 我已编辑问题以添加您的评论,因为我认为这是一个好问题。
  • 好的。你的描述还是很笼统的。我认为如果你能添加一个具体的例子会很有帮助。我很确定单身人士是个坏主意。也许,B 应该将 C 传回给 A,A 可以添加必要的数据?
  • 这是具体的例子。 Class-B 是一个可以生成不同类型的类的类,但它不知道关于它所生成的类的信息。它的工作只是生成一个类,通过参数为生成的类提供它所需的一般信息,最后进行一些额外的设置。但是 B 类不应该知道其类产生的其他特定数据。所以它不会知道 C 类需要去 A 类获取它的信息。只有 C 类知道从哪里获取其特定信息。那么单身在这里还可以吗?.. sorta?
  • 顺便说一句,使用“代码气味”这个短语很好地表明有人试图将自己的风格选择提升到伪科学的水平。 任何东西都可以这样标记,无需证据,编码界的潮人会齐声谴责它。

标签: design-patterns singleton factory-pattern anti-patterns cocoa-design-patterns


【解决方案1】:

我对“生成类”的概念有点迷茫。

你说 C 有成员(即它是一个服务类吗?),那么假设 C 被称为 Cook,它有一个名为

的成员
  Cake bakeACakeMethod(Flour,Chocolate)

Chocolate 是您所说的 B 类。

既然你想跳过 B 类并直接在 C 中使用 A 类(菠萝),那么你可以将方法更改为

  Cake bakeACakeMethod(Flour,IYummy)

其中 IYummy 是一个接口,而 A 和 B 类实现了 IYummy,因此该方法允许这两个类。

其他方法是使用重载

【讨论】:

  • 产生一个类意味着创建一个新的类实例。 Class-(B) 在这里遵循工厂模式:en.wikipedia.org/wiki/Factory_%28object-oriented_programming%29。它是一个创建其他类的可重用类。所以类(A)读取初始数据,并实例化(B)。 (B) 然后根据从 (A) 传递给它的数据实例化一个适当的类。它实例化 (C) 并将一般数据传递给它。 A、B 和 C 类是完全独立的类(不涉及继承/子类化)。因此 (C) 不能在 (A) 上调用方法,除非它对 (A) 有一些引用。我使用单例获取参考(A)
  • 我还编辑了上面的问题,删除了“spawned”一词并将其替换为“instanced”类
猜你喜欢
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-22
相关资源
最近更新 更多