Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 我应该避免定义';对象';在斯卡拉?_Scala_Design Patterns - Fatal编程技术网

Scala 我应该避免定义';对象';在斯卡拉?

Scala 我应该避免定义';对象';在斯卡拉?,scala,design-patterns,Scala,Design Patterns,我认为Scala中的“对象”与Java中的Singleton非常相似,这被认为不是一个好的设计实践。对我来说,Singleton就像定义全局变量的另一种方式,这很糟糕。我编写了一些类似这样的Scala代码,因为它很简单,而且可以工作,但代码看起来很难看: object HttpServer { // I'm the only HttpServer instance in this program. var someGlobalState: State def run() { //

我认为Scala中的“对象”与Java中的Singleton非常相似,这被认为不是一个好的设计实践。对我来说,Singleton就像定义全局变量的另一种方式,这很糟糕。我编写了一些类似这样的Scala代码,因为它很简单,而且可以工作,但代码看起来很难看:

object HttpServer { // I'm the only HttpServer instance in this program.
  var someGlobalState: State
  def run() {
    // do something
  }
}

我尽量避免这样做。什么时候定义Scala对象比较好?

全局变量本身并不坏。你只需要知道什么时候合适。因此,
对象
本身并不坏。例如:

object HelloWorld {
  def main(args:Array[String]){
     println("Hello World")
  }
}
在不深入讨论这个话题的情况下,我喜欢这样想:“我想要这些东西中的‘只有一个’是因为它最能反映现实吗?还是这是一条让事情‘正常运转’的懒惰捷径?”


不要盲目而广泛地应用“单身是坏的”规则。在很多情况下,“只有一件”是有意义的。在您的特定情况下,我需要更多的上下文来给出更具体的建议。

否。许多Scala库严重依赖对象

Singleton模式的主要目标是只存在一个对象实例。对象也是如此

您可能会将其误用为全局变量,但这不是重点


例如,对象是工厂方法的好地方,或者是保存函数的模块的替代品。

为什么假设只需要全局变量?全局值和方法非常有用。这是您将在Scala中使用的
object
的大部分内容

object NumericConstant {
  val Pi = 3.1415926535897932385   // I probably will not change....
}

object NumericFunctions {
  def squared(x: Double) = x*x     // This is probably always what we mean...
}
现在,您必须小心使用全局变量,如果您愿意,您可以在对象中实现它们。然后,您需要弄清楚自己是否粗心大意(注意:将同一个类的实例传递给程序中的每个类和方法同样有问题),或者您正在执行的操作的逻辑是否最好地由单个全局值反映出来

这里有一个非常非常糟糕的主意:

object UserCache {
  var newPasswordField: String = "foo bar"
}
两个用户同时更改他们的密码,然后…嗯…你会有一些不开心的用户

另一方面,

object UserIDProvider {
  private[this] var maxID = 1
  def getNewID() = this.synchronized {
    var id = maxID
    maxID += 1
    id
  }
}

如果你不这样做,同样,你会有一些不高兴的用户。(当然,您确实需要在启动时读取磁盘上有关用户ID号的一些状态……或者将所有这些信息保存在数据库中……但您明白了这一点。)

var someGlobalState的可能重复项解决了您的问题。Scala对象并不意味着全局状态或任何状态。经验法则:
object
s不应该有任何可变状态。(有时可能会被破坏,但这些情况应该以怀疑的态度处理。)是的,你必须小心测试。在很多领域,全球性的事情会让你陷入麻烦。对于一个相对初学者来说,即使没有单例测试,创建一个测试噩梦(可以说)也是相当容易的。我认为在您的示例中使用像UserIDProvider这样的对象不是一个好方法。它向任何人公开此对象。您可以在代码中的任何位置操作此对象中维护的全局状态。有时我很懒,不想太费劲地考虑谁需要访问这个对象,我只将它们定义为单例。我可以在以后的任何时候访问它们,而无需更改任何内容。但我认为将对象范围限制在尽可能小的范围是一种好的做法。@woodings-这取决于应用程序的范围。如果它真的关心新的用户ID——也许它是一个新的帐户服务器——那么全局就可以了。如果它只是某个巨大系统的一小部分,那么不,你可能不希望它随处可见。然而,解决这个问题的正确方法是——如果这真的是一个单一的全局问题——对单个对象使用访问限制。如果您试图通过仅实例化一个对象来模拟它,则可能会犯错误并创建两个对象。这样,编译器会为您处理它。所以,
private[无论什么]对象
it。