代码之家  ›  专栏  ›  技术社区  ›  Kenan Banks

关于命名空间全局对象和单例对象,我的观点如何?

  •  2
  • Kenan Banks  · 技术社区  · 15 年前

    我的同事想在javascript中使用单例模式来引用对象,在我们当前的应用程序中,这些对象只能创建一次。

    相反,我想使用一个命名空间的全局对象来引用这些对象。

    他的观点是,如果允许创建多个对象,那么使用单例时重构成本会更低,因为需要更改的代码会更少。

    例如,假设我们有一个带有大型中央界面元素的应用程序,比如谷歌地图中的地图。

    我通常希望通过以下应用程序代码访问地图:

    Application.interface.map.zoom(10);
    

    他希望在整个应用程序代码中访问地图,如:

    var map = new Map(); // This is invisibly a singleton
    map.zoom(10);
    

    例如,在 ButtonsControl 表示控制地图的按钮的类必须以某种方式访问地图以反映用户输入。它应该使用 new 或 Application ?

    在我们的应用程序中,我们不太可能创建另一个map实例,但假设有一天我们会这样做。。。

    我的观点是,现在阅读像他(使用 新 )超过了我们以后在重构代码以允许多个映射时可能获得的任何好处。阅读像他这样的代码并试图理解它的功能会产生成本。

    例如,在中读取代码时 按钮控制 ,你可能会惊骇地看到,显然,一个 new Map() 是在你的 按钮控制 构造函数,并被迫调查Map的代码,以确保这不是真的发生。要么追踪,要么已经知道了 新地图() 单身是使用手机的成本 新地图() ,而阅读 Application.interface.Map 是显而易见的,不会对未来的代码读者征税。

    即使 新地图() 语法更改为 Map.get_instance() ,我的论点是,如果我们选择某一天允许多个映射,使用单例实际上会导致以后的更多工作,因为围绕单例编写的代码实际上会表现得好像它在特定映射上工作很重要,而不是可能创建一个新映射并对其进行操作 信息技术 换句话说,我想知道是否使用单例的一个好测试是,围绕它的代码似乎不知道它是在一个真正的新对象上运行还是在一个现有对象上运行。例如,数据库连接的规范示例通过了此测试。

    我知道信息不多,但是。。。这就是为什么制定编码标准很难;如果没有完美的信息,很难做出这些决定。但假设你今天白手起家地设计谷歌地图,并做出了这个决定。我也知道这是一个可笑的小问题,但出于某种原因,我直觉上强烈倾向于我的版本,我试图理解为什么。

    你选择哪一个?为什么?

    3 回复  |  直到 15 年前
        1
  •  3
  •   user187291    15 年前

    我认为这两种方法都更糟糕。我同意你对“new”令人困惑的感觉,但是“Application.interface.map”除了过于冗长之外,将来肯定会成为重构的噩梦。

    我会避免任何类型的全局变量,将“大var”作为参数传递给任何需要它的人,并将其锁定在闭包中。

     function initButton(map) {
        someButton.onclick = function() { map.zoom() }
     }
    

    只要使用一个映射,“main”函数也可以是闭包。

    (function(map) {
    
         // init things here
    
    }) ( someInstanceOfMap )
    

    当你决定使用多个映射时,你只需要重构这个主函数。

        2
  •  2
  •   Victor Nicollet    15 年前

    就设计而言,语法是无关紧要的。如果一段代码假设只有一个映射,那么在应用程序需要使用两个映射的那一天,需要重写这段代码。这一假设是否以“地图是通过 Application.interface.map 或者“地图是用 new Map “一点都不重要。

    我同意更合适的类名是 new MapRef 或 new MapProxy ,因为您正在创建对现有地图的新引用,而不是新地图。这将减轻读者的疲劳,并使代码与单例代码一样脆弱(因为,同样,您创建的是代理,而不是映射,所以首先必须有一个要代理的映射)。但除此之外,这两种解决方案在设计上是等效的。

    设计这种映射的干净方法是将映射作为参数提供给所有使用它的函数(直接提供,或作为该函数可用对象的成员提供)。即使在页面上的任何给定时间都不会有多个映射,您可能仍然希望运行单元测试(这可能涉及创建 嘲弄 地图)。

    作为记录,你同事的建议被称为 Monostate 模式,就对设计的影响而言,这在很大程度上相当于一个单件。

        3
  •  1
  •   Tom Anderson    15 年前

    你同事的想法太疯狂了。在构造函数中隐藏一个单例是一件有害的、可怕的事情。

    更重要的是,当你说:

    对于是否使用单例,一个很好的测试是,它周围的代码似乎不知道它是在一个真正的新对象上运行还是在一个现有对象上运行。

    而且,正如你所担心的,只要你真的有一个单例,不管它是如何实现的,你都会像有一个单例一样写作。

    好的一面是,听起来你很有可能只生一个单身汉。在这种情况下,雅格尼适用,你应该做最简单的事情,现在可能工作,并担心如何修复它,如果它发生了,你需要。