【问题标题】:Should a single object used throughout the app be static?整个应用程序中使用的单个对象是否应该是静态的?
【发布时间】:2014-06-28 10:52:48
【问题描述】:

我正在编写一个基于历史价格分析股票的 C# 应用程序。我有一个保存数据(历史价格)的对象。所有数据都保存在这个对象中 - 我只需要它的一个实例,并且数据被整个应用程序中的许多其他对象使用。

鉴于上述情况,让这个对象静态化不是更容易(也是更好的设计)吗?因为替代方案是我目前正在做的 - 在对象之间传递对同一个实例的数十个引用。

我仍然犹豫的原因是我知道static 对象应该被小心对待,因为我已经阅读了this answer。就我而言,该对象不是一个简单的实用程序对象,也不是无状态的。数据正在加载到对象中并对其进行更改,但我的想法是这些更改仍需要在所有其他对象之间共享,我知道我不需要此数据对象的两个不同实例。

对于我的案例,您认为最好的方法是什么?有没有我没有考虑过的替代解决方案?

【问题讨论】:

    标签: c# design-patterns static


    【解决方案1】:

    您可以将其设为静态或使用Singleton 设计模式。我会使用单例。

    无需传递引用,Singleton 提供了一个全局访问点。

    例子:

    public class Singleton
    {
        private static Singleton instance;
    
        private Singleton()
        {}
    
        public static Singleton GetInstance()
        {
            if(instance == null)
               instance = new Singleton();
    
            return instance;
        }
    }
    

    私有构造函数和GetInstance() 函数确保对象只有一个实例。

    如果您需要获取对对象的引用来调用对象内部的函数,请使用:

    Singleton.GetInstance().FunctionName();
    

    另外,这是惰性实例化,不是线程安全的(多线程程序),但您可以自己了解更多,这应该很有趣!

    【讨论】:

      【解决方案2】:

      如果您的对象有状态,那么而不是使其静态或单例,我建议使用dependency injection design pattern

      这样,您可以根据情况用不同的对象或类替换该对象或类,例如一个用于生产代码,另一个用于测试。

      实例可以用各种依赖注入样式解析,例如

      • 构造函数注入

      • 属性注入

      • 控制容器的反转(例如CommonServiceLocator

      • 配置文件

      在所有这些选项中,您使用要使用的公共协定定义一个接口或基类,然后在使用代码之外确定实现该接口的实际类/实例,这样您就可以在不更改该代码的情况下更改决定.

      【讨论】:

      • 我认为这里要强调的一点是无法进行依赖注入不使用单例模式或静态类的原因。无论如何,IoC 容器和服务定位器通常都有一种将类型绑定到单例的好方法。
      • @BenAaronson 我假设对于许多会问这个问题的人来说,依赖注入的重要性对他们来说并不清楚,否则他们甚至不会考虑单例或静态类。这就是为什么我没有这么直率。
      【解决方案3】:

      对于你想要的,我会说单例。这一切都归结为偏好。静态使得你的类不能被实例化,所以你使用className.myMethod()。如果您的数据检索没有在构造函数中完成并且您使用一种方法来提取数据,那很好。但是,如果您的构造函数具有连接凭据,则需要将其移至可以调用的新方法。单例可以限制为单个实例。您可以同时测试两者,看看哪个最适合您。

      【讨论】:

        【解决方案4】:

        使用单例模式怎么样? http://en.wikipedia.org/wiki/Singleton_pattern 没有引用必须通过。它可能有助于更轻松地再次更改设计。

        【讨论】:

        • 单例并不意味着静态,所以它可能仍然需要传递引用
        • 它不是静态的,但不知何故非常接近它。您只能拥有此类的一个实例。 (如果你做得对的话)你可以通过调用 MyNewSingeltonClass.getInstance().testMethod()/testmember 轻松获得它,因为 getInstance 是一个静态方法。来自世界各地。
        • @jordan 不正确,请阅读我的回答。 Singleton 提供了一个全局访问点。
        • 是的,使用您提供的解决方案可以绕过传递实例。这样做会导致无法测试所有依赖于此的代码。是的,在测试期间有一些黑客可以解决这个问题,但同样,它们是黑客。如果您传递实例,那么您可以模拟它并允许测试覆盖。否则这个全球接入点会使测试变得困难。此外,如果将来您将其更改为不是单例,则不需要更改任何依赖项。
        • 还有您的报价“您可以将其设为静态或使用单例设计模式。”同意我的第一个说法,即它们是不同的东西。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-17
        • 2023-03-05
        • 1970-01-01
        • 2012-02-07
        • 1970-01-01
        • 2014-03-23
        • 1970-01-01
        相关资源
        最近更新 更多