代码之家  ›  专栏  ›  技术社区  ›  mattlant

你认为这是一个单例/单例模式吗?

  •  3
  • mattlant  · 技术社区  · 16 年前

    想象一下,在global.asax.cs文件中,我有一个实例类作为私有字段。让我们这样说:

    private MyClass _myClass = new MyClass();
    

    我在全局上有一个名为getMyClass()的静态方法,它获取当前的httpApplication并返回该实例。

    public static MyClass GetMyClass()
    {
        return ((Global)HttpContext.Current.ApplicationInstance)._myClass;
    }
    

    所以我可以通过调用global.getMyClass()来获取当前请求httpApplication的实例。

    请记住,有多个(全局)http应用程序。每个请求都有一个http应用程序,它们被合并/共享,因此在最真实的意义上,它不是一个真正的 singleton . 但它确实在某种程度上遵循了这种模式。

    因此,正如问题所问,你会认为这至少是单例模式吗?

    你会说它不应该使用吗?你会阻止它的使用吗?你能说这是一个 可能地 不好的做法就像一个真正的单身汉。

    您能看到这种类型的使用场景可能产生的任何问题吗?

    或者你会说这不是一个真正的单身,所以这是可以的,并不是坏的做法。如果每个请求需要一个实例,您是否建议将其作为半类单例?如果不是,你会使用/给出什么其他模式/建议?

    你用过这样的东西吗?

    我在过去的项目中使用过这个方法,但我不确定是否应该远离它。不过,我过去从来没有遇到过任何问题。

    请把你的想法和意见告诉我。

    我不是在问单身汉是什么。在很多情况下,如果使用不当,我认为是单例错误做法。那就是我。然而,这不是我想要讨论的。我正试图讨论我给出的这个场景。

    6 回复  |  直到 8 年前
        1
  •  4
  •   Ben Scheirman    16 年前

    无论这是否符合单例曲奇模式,它仍然面临着与单例相同的问题:

    • 它是一个静态的、具体的参考,不能代替单独的行为,也不能在测试过程中用作存根/模型。
    • 您不能将此子类化并保留此行为,因此很容易绕过此示例的单例性质。
        2
  •  4
  •   Cowan    16 年前

    我不是.NET用户,因此我不会对此发表评论,除了以下部分:

    你能说它的坏做法像一个真正的单身汉。

    真正的单身不是“坏习惯”。它们被过度使用了,但这不是同一回事。我最近读了一些东西(不记得在哪里,唉),有人指出——‘想要还是需要’和‘可以’。

    “我们只想要其中的一个”,或者“我们只需要其中的一个”:不是单件的。

    “我们只能拥有其中的一个”:辛格尔顿

    也就是说,如果拥有两个这样的物体的想法会以可怕和微妙的方式打破某些东西,是的,使用一个单独的。这是真的,比人们想象的要少得多,因此单子核的扩散。

        3
  •  3
  •   James Curran    16 年前

    单件是一个对象,其中只能有一个。

    现在刚好有一个的对象不是单例对象。

        4
  •  2
  •   Kevin Dostalek    16 年前

    既然您谈论的是Web应用程序,那么您需要非常小心地使用静态类或此类伪单例,因为正如DavidB所说,它们只在该线程中共享。如果将IIS配置为使用多个工作进程(使用不正确的“Web花园”模式配置,但也可以在machine.config中设置工作进程),则会遇到问题。假设这个盒子有多个处理器,任何试图调整它性能的人都必须打开它。

    对于这种情况,更好的模式是使用httpcache对象。它本质上已经是线程安全的,但是仍然吸引大多数人的是,您的对象还需要是线程安全的(因为您只需要创建实例,然后随着时间的推移读/写它的许多属性)。下面是一些框架代码,让您了解我在说什么:

    public SomeClassType SomeProperty
    {
        get
        {
            if (HttpContext.Current.Cache["SomeKey"] == null)
            {
                HttpContext.Current.Cache.Add("SomeKey", new SomeClass(), null,
                                  System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromDays(1),
                                  CacheItemPriority.NotRemovable, null);
            }
            return (SomeClassType) HttpContext.Current.Cache["SomeKey"];
        }
    }
    

    现在,如果您认为您可能需要一个Web场(多服务器)规模的路径,那么上面的路径将不起作用,因为应用程序缓存不会跨机器共享。

        5
  •  1
  •   Amy B    16 年前

    暂时忘掉单身吧。

    您有返回应用程序状态的静态方法。你最好小心点。

    如果两个线程访问此共享状态…繁荣。如果您生活在Web服务器上,您的代码最终将在多线程上下文中运行。

        6
  •  0
  •   Peter Mortensen sifr_dot_in    8 年前

    我想说这绝对不是单件的。设计模式作为常见编码实践的定义最有用。当你谈论单例时,你谈论的是一个只有一个实例的对象。

    正如您自己所指出的,有多个http应用程序,因此您的代码不遵循单例的设计,也没有相同的副作用。

    例如,可以使用单例更新货币汇率。如果此人在不知情的情况下使用了您的示例,他们将触发七个实例来完成“只有一个对象”本应执行的任务。