我所读到的是不可变性意味着一旦分配的值保持不变,即一旦分配,它就会在代码中反映为相同的值。
大多数不可变性在多线程环境中的函数式编程范例中使用。
但是
单例模式是否也能解决相同的目的,
请在下面找到用java编写的单例,
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中编写了单例,
如下
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$
在Singleton模式的两个(即javaScript和java)实现中 你可以看到对象的状态保持不变,它不会改变。
即使我们重置了对象的值, 输出给出最新的重置值。
使用Singleton模式我在我的对象代码中获得了Immutability" Student" ?
答案 0 :(得分:1)
不是。
不可变类也并不意味着你不能创建同一个不可变类的更多对象。对于单例,通常每个JVM需要一个实例才能将其称为单例。
不可变意味着一旦分配的值不能改变,所以通常你不会在不可变的情况下使用setter方法,但是对于singleton没有这样的要求。但单例更多是从内存的角度来看,只有一个实例会存在。你不能改变实例,但是你可以使用单例来保存你想要的任何值,你也可以在任何时间点改变它。
e.g。我们使用singleton类作为服务定位器。我们可以根据需要在任何给定的时间点更改服务。同样,我可以使用相同的变量创建2个不可变类的对象,但保持不同的值。
希望这有帮助。
答案 1 :(得分:1)
不:单身和不变性是正交的。单身可以是可变的或不可变的;非单身人士可以是可变的或不可变的。
但是,如果在多个线程中使用单例,则必须是线程安全的;不可变对象本质上是线程安全的。
你的Student
类大致是单例,但不是不可变的:你有一个改变成员变量的setter方法的类不能不可变。
但是,您的Student
类不是线程安全的,甚至安全:
name
的值,但无法保证其他线程中name
字段的可见性:因为您不同步对变量的访问(或使用AtomicReference
或volatile
),一个线程可能会更新名称,但其他线程可能会继续查看旧值。因此,您可能会观察到线程干扰效应。INSTANCE
字段为空,这意味着任何试图在任何时候访问该字段值的人都必须首先检查它是否为空。通过制作字段final
可以很容易地解决这个问题。但最好只是将类变成单元素枚举。答案 2 :(得分:0)
首先,您提供的单例示例实际上并不是单例。
单例模式迫使您在整个应用程序中每个类只使用一个对象。在您的示例中,可以创建尽可能多的对象。
强制单个对象创建可以使用私有构造函数实现,并且每当对象的请求使用一些静态方法getInstance()来提供'INSTANCE'。
不变性有不同的目的。它主要与物体的安全性有关,例如创建对象后,您无法更改其状态。
显然你必须在创建该对象时提供状态。我的意思是你需要一个参数化构造函数来为该对象分配一个永久状态。
所以基本的区别是:
Singleton:在任何情况下你都不能拥有更多的那个对象。(与不可变对象不同,你不仅限于状态改变,但大多数情况下你并不想改变单个对象的状态)
不变性:在任何情况下都无法改变对象的状态,但是你可以拥有与堆许可一样多的对象; - )
答案 3 :(得分:0)
你的学生班几乎是不可改变的。 Student类的public setName()可以防止状态变为不可变。不可变对象无法更改其状态。
如果您的对象是不可变的,则您的学生实例Student.INSTANCE
无法更改其名称。但是,你多次改名。最后systemOut
确认可变性: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);
此外,如果不可变对象想要提供与状态修改相关的操作,它将不会应用于实例本身,而是返回具有此新状态的对象的新实例。