Javascript 不变性和单例解决了同样的问题吗?

Javascript 不变性和单例解决了同样的问题吗?,javascript,java,design-patterns,singleton,immutability,Javascript,Java,Design Patterns,Singleton,Immutability,我读到的是不变性,这意味着赋值后的值保持不变,也就是说,赋值后的值在代码中反映为相同的值 在多线程环境中,函数式编程范式主要使用不变性 但是 单例模式是否也解决了同样的问题 请在下面找到用java编写的singleton package com.main; class Student{ private Student(){ } public static Student INSTANCE; static{ INSTANCE = new Student(); }

我读到的是不变性,这意味着赋值后的值保持不变,也就是说,赋值后的值在代码中反映为相同的值

在多线程环境中,函数式编程范式主要使用不变性

但是

单例模式是否也解决了同样的问题

请在下面找到用java编写的singleton

 package com.main;

class Student{
  private Student(){

  }
  public static Student INSTANCE; 
  static{
    INSTANCE = new Student();
  }

  private String name;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  @Override
  public String toString(){     
    return "Student is "+this.name;
  }
}


public class SingletonTest {

  /**
   * @param args
   */
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    Student student = Student.INSTANCE;
    student.setName("Arnold");

    student = Student.INSTANCE;
    student.setName("Kevin");

    student = Student.INSTANCE;
    student.setName("Jim");

    student = Student.INSTANCE;
    student.setName("Falcon");

    student = Student.INSTANCE;
    student.setName("Sarvik");


    student = Student.INSTANCE;
    System.out.println(student);

  }

}
上述代码的输出是

Student is Sarvik
同样,我也用javaScript编写了singleton

如下

var Student = (function(){
  var name = "";
  var obj = {
    setName : function(studentName){
        name = studentName;
    },
    getName : function(){
        return name;
    }
  }

  return {
    INSTANCE : obj
  }
})();


var student = Student.INSTANCE;
student.setName("Arnold")

student = Student.INSTANCE;
student.setName("Kevin");

student = Student.INSTANCE;
student.setName("Jim");

student = Student.INSTANCE;
student.setName("Falcon");

student = Student.INSTANCE;
student.setName("Sarvik");

student = Student.INSTANCE;

console.log("Student is "+student.getName());
结果如下

rahul@rahul:~/myPractise/JavaScript-DesignPatterns$ node singleton.js 
Student is Sarvik
rahul@rahul:~/myPractise/JavaScript-DesignPatterns$ 
在单例模式的两种(即javaScript和java)实现中 您可以看到对象的状态保持不变,它不会改变

即使我们重置了object的值, 输出给出最新的重置值

那么,使用单例模式我在对象“Student”的代码中获得了不变性吗

不太可能

不可变类也并不意味着不能为同一个不可变类创建更多的对象。对于singleton,通常每个JVM需要一个实例才能将其称为singleton

Immutable意味着一旦分配的值就不能更改,所以通常您不会在Immutable中使用setter方法,但是对于singleton没有这样的要求。但从内存的角度来看,单个实例更重要,只有一个实例可以生存。您不能更改实例,但是您可以使用单例来保存您想要的任何值,并且您也可以在任何时间点更改它

e、 我们使用singleton类作为服务定位器。我们可以根据需要随时更改服务。同样,我可以创建两个不可变类的对象,它们具有相同的变量,但包含不同的值


希望这有帮助。

首先,您给出的单例示例实际上不是单例

单例模式强制您在整个应用程序中每个类只使用一个对象。在您的示例中,可以创建尽可能多的对象

可以使用私有构造函数强制创建单个对象,并在每次使用静态方法(如getInstance())向该类发出对象请求时提供“实例”

不变性有不同的目的。它主要与对象的安全性有关,例如,一旦创建对象,就不能更改其状态

很明显,您必须在创建该对象时提供状态。我的意思是你需要一个参数化的构造函数来为这个对象指定一个永久的状态

所以基本的区别是:

Singleton:在任何情况下都不能有多个对象。(与不可变对象不同,您不受状态更改的限制,但大多数情况下不应更改Singleton对象的状态)


不变性:在任何情况下都不能更改对象的状态,但可以拥有堆允许的任意多个对象;-)

你的学生班几乎是一成不变的。Student类的public setName()防止状态不可变。不可变对象无法更改其状态。

如果对象是不可变的,则学生实例
student.instance
无法更改其名称。但是,您多次更改其名称。最后,您的
systemOut
确认了可变性:姓“setted”由
toString()方法显示

Student student = Student.INSTANCE;
student.setName("Arnold");

student = Student.INSTANCE;
student.setName("Kevin");

student = Student.INSTANCE;
student.setName("Jim");

student = Student.INSTANCE;
student.setName("Falcon");

student = Student.INSTANCE;
student.setName("Sarvik");


student = Student.INSTANCE;
System.out.println(student);

此外,如果不可变对象希望提供与状态修改相关的操作,它将不应用于实例本身,而是返回具有此新状态的对象的新实例。

否:单一性和不可变性是正交的。单个个体可以是可变的,也可以是不可变的;非单例可以是可变的或不可变的

但是,如果在多个线程中使用,则单个线程必须是线程安全的;不可变对象本质上是线程安全的



您的
Student
类大约是单例的,但不是不可变的:任何具有改变成员变量的setter方法的类都不能是不可变的

但是,您的
学生
类不是线程安全的,甚至不是安全的:

  • 您可以更改
    名称
    的值,但不能保证
    名称
    字段在其他线程中的可见性:因为您不同步对变量的访问(或使用
    原子引用
    ,或
    volatile
    ),所以一个线程可能会更新名称,但是其他线程继续看到旧的值。因此,您可能会观察到线程干涉效应
  • 类的用户可以将
    实例
    字段清空,这意味着任何试图在任何时候访问该字段值的人都必须首先检查该字段是否为null。这很容易通过将字段设置为final来解决;但最好是将类简化为单个元素枚举

单例性和不变性是正交的。单个个体可以是可变的,也可以是不可变的;非单例可以是可变的或不可变的。但是,如果在多个线程中使用,则单个线程必须是线程安全的;不可变对象本质上是线程安全的。您的
Student
类显然不是不可变的:您有一个setter方法。我在java实现中将Student构造函数设置为私有的哦,太棒了!忽略我答案的前三行。希望7-3=4行对您有所帮助;-)