【问题标题】:Need advice on OOP philosophy需要有关 OOP 理念的建议
【发布时间】:2011-02-21 04:35:03
【问题描述】:

我正在尝试在 C# 中启动一个大型项目。我以前的经验是在 Delphi 中,默认情况下,每个表单都是在应用程序启动时创建的,并且表单引用保存在(gasp)全局变量中。所以我试图让我的想法适应一个 100% 面向对象的环境,但我的脑袋有点晕。

我的应用程序将包含大量类这些类中的大多数实际上只需要一个实例。所以我在想:静态类。我不太确定为什么,但我在这里读到的大部分内容都说,如果我的类要保持一个状态,我认为这意味着任何属性值,我应该使用单例结构。好的。但是有些人出于我无法理解的原因,认为单身人士也是邪恶的。

这些类都没有在除此程序之外的任何地方使用的危险。所以它们当然可以作为常规对象正常工作(与单例或静态类相比)

然后是对象之间的交互问题。我很想创建一个全局类,其中包含许多引用这些类的单个实例的公共静态属性。我还考虑过让它们成为 MainForm 的属性(静态或实例,不确定是哪个)。然后我会让我的每个班级都知道 MainForm 作为所有者。然后各种对象可以相互引用为 Owner.Object1、Owner.Object2 等。

我担心我的电子墨水快用完了,或者至少让任何愿意和我坚持这么久的人耐心等待。我希望我已经清楚地解释了我完全混乱的状态。我只是在寻找一些关于我的情况的最佳实践的建议。欢迎并感谢所有意见。

提前致谢, 大卫詹宁斯

【问题讨论】:

  • 您可以从 Delphi 表单中删除全局变量,并根据需要实例化和释放它们。
  • 感谢所有花时间回复的人。你给了我很多思考。多么棒的社区。我必须承认,当我说我的大部分课程只需要一个实例时,我夸大了。事实是它只有大约 12 个中的 3 个。再次感谢您鼓励我退后一步,仔细查看我的一些班级决定。在我加快速度的同时,这个网站将成为我最重要的 C# 智慧来源之一。

标签: c# oop static singleton global


【解决方案1】:

从过程语言或其他非 OOP 语言出发并认为“每个 XYZ 一个巨大的静态类”是很正常的,这通常意味着您没有真正考虑过所表示的 OBJECTS,因为一个类应该表示被操纵的对象。

因此,您需要退后一步,看看 DATA 以及 DATA 代表什么。你可能会说,“嗯,它是数据!它代表数字!”,但你必须抽象出数据代表什么。数据所代表的“事物”是对象。您对“事物”所代表的数据执行的操作将成为您的方法。

【讨论】:

  • 这个项目实际上是对我大约 8 年前在 Delphi 开发的一个系统的重写。从那以后,我一直在维护和改进应用程序,我刚刚决定是时候将 Delphi 抛在后面了。 Delphi 是一种面向对象的语言(主要是)。它只是混合了全局存储部分(大多数面向对象的程序员,毫无疑问,认为这是令人畏惧的)。因此,就数据/行为到类的翻译而言,我认为我已经准备好了。我有点挣扎的地方是想办法把全球空间抛在脑后。
【解决方案2】:

您可以尝试一下,看看效果如何。考虑在您身边使用 NUnit 进行开发;如果这样做,您会发现您的代码将保持足够的灵活性,以至于进行架构更改不会太困难。

我的偏好是避免使用静态类和静态数据,但有时它只对近期问题有意义。对此,我的建议是考虑实际拥有各种形式的东西。很多时候,人们似乎想让主窗体成为“主要的应用程序”,但实际上该窗体可能有更好的所有者。

无论如何-除了谈论和思考可能发生的事情之外,我建议继续尝试一些选项,看看它们会做什么。编写软件后不要害怕更改软件!

【讨论】:

  • 谢谢。这是我开始的态度。无论我如何处理这些特定问题,我都相信我可以使应用程序正常工作。我只是想在这个过程中学到一些东西,同时也防止应用程序一开始就变得一团糟。 :)
【解决方案3】:

单例通常是我们在设计中经常看到的许多问题的根源。不过,我考虑同时创建单例和全局变量,作为将它们作为代码异味在应用程序中传递的一种方式。

我觉得最好让自己了解SOLID 原则。还有一些关于这个主题的视频,你应该观看和理解。

我推荐的另一本实用书籍是 Kent Beck 的《实施模式》。了解 OOP 是一回事,而在现实世界中实施则是另一回事。

了解 Windows Presentation Foundation,这是一种用于构建 Windows 客户端应用程序的下一代演示系统。

我想我已经用足够多的信息轰炸了你,但请放轻松,一步一步来。我觉得你应该在这里跟随几条轨道到达你想去的地方。微软提供了一些 prototypes,您可以从中学习,然后使用 OOP 即兴发挥。

【讨论】:

    【解决方案4】:

    关于这个可能有用也可能没用的一些随机想法:

    • 从数据而不是程序结构开始。分析数据并找出您在概念上试图表达的内容,然后将其具体化。

    • 我的经验是,使用程序代码时,您会想“我现在在做什么?”但是对于 OO 代码,您会想“有一天我想做什么?”

    • 总会有至少一个主对象,即使那是应用程序对象本身。即使它很诱人,也不要在这个对象上放太多。您在概念上相关的对象中表示的数据、状态和行为越多,新开发人员就越容易学习和维护该应用。

    • 做一个原型。构建您知道会丢弃的应用的缩小版本,然后当您到达某个点时检查您的代码,确定哪些对象运行良好,哪些没有,然后重新开始。

    至于整个 Singleton 的事情 - 并且不想挑衅 - 忽略反对者。有时单例设计模式非常有用,就像有时 EAV 数据模型是完美的,而 MVC 是世界上最糟糕的事情一样。如果需要拧螺丝,请使用螺丝刀。

    【讨论】:

      【解决方案5】:

      在阅读您的解释时,我的一部分认为,如果您有那么多您认为应该是静态或单例的类,那么您可能仍在思考一种 Delphi 范式。我不知道我是否曾经遇到过一个只有大多数对象之一的项目。所以我的倾向是你的对象分解可能有缺陷。

      确实,您应该开始考虑您在程序中所代表的内容。问问自己,如果你有很多只有一个实例的对象,为什么只有一个实例?是不是因为您以一种奇怪的方式保存数据,例如拥有多个索引匹配的数组。

      话虽如此,C# 确实为单例提供了一些很好的内置语义,因为您不必在实例方法中进行空值检查

      public class SingletonClass{
           private static SingletonClass _instance;
      
           private SingletonClass(){}
      
           public static Instance
           {
               get
               {
                   if(_instance == null){
                      _instance = new SingletonClass();
                   }
               }
           }
      
      }
      

      在C#中可以写成:

      public class SingletonClass{
           private static SingletonClass _instance = new SingletonClass();
      
           private SingletonClass(){}
      
           public static Instance
           {
               get
               {
                  return _instance;
               }
           }
      
      }
      

      因此,如果您坚持使用该模式,我建议您倾向于使用单例。单例,就像一切都有时间和地点一样,我不会编写一个大多数对象都是单例的整个应用程序。

      我强烈建议您考虑一下为什么您有一个带有静态方法或单例的全局状态。

      【讨论】:

        【解决方案6】:

        静态类和单例有相同的缺点:

        • 与许多其他类紧密耦合
        • 隐藏依赖项(很难说其他类使用它们)
        • 测试困难
        • 基本上是全局数据
        • 对于单身人士,多重职责(无论他们做什么 + 生命周期管理)

        许多(不是全部!)情况下的解决方案是Dependency Injection (DI),它基于Dependency Inversion Principle(@CodeToGlory 提到的SOLID 原则之一)。这可以手动完成,也可以使用DI Container framework

        Mark Seemann 在Dependency Injection in .NET 上有一本很棒的书;我强烈推荐。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-04-16
          • 2019-02-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-11
          相关资源
          最近更新 更多