黑马程序员技术交流社区
标题:
学习单例模式心得
[打印本页]
作者:
lpf870826
时间:
2015-1-10 13:40
标题:
学习单例模式心得
本帖最后由 lpf870826 于 2015-1-10 13:52 编辑
单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问他的全局访问点,通常我们可以让一个全局变量使得一个对象被访问,但他不能防止实例化多个对象。一个最好的办法就是,让类自身负责保存他的唯一实例。这个类可以保证没有其他实例可以被创建,并且他可以提供一个访问该实例的方法。
所有类都有构造方法,不编码则系统默认生成空的构造方法,如重写构造方法,则默认的构造方法就会失效。
public class Singleton {
/**
*利用一个静态变量记录Singleton类的唯一实例。如果没有“static”修饰,下面的
*getSingleton()方法不能引用非静态变量singleton。“volatile”修饰符
*保证了内存可见,即如果该变量有变化(这里的变化就是被实例化),
*多个线程能及时看到singleton变量的变化。
*/
private volatile static Singleton singleton;
//构造私有的构造函数,只有在Singleton类内才可以调用
private Singleton() {}
//getSingleton()方法提供了一个全局访问点
public static Singleton getSingleton() {
//利用双重锁,首先检查实例是否已经创建,如果没有创建才进行同步,
//如果创建过就直接返回,不需要加锁。
//如果对整个方法使用synchronized加锁则会造成效率降低。
if (singleton == null) {
synchronized (Singleton.class) {
/**
*如果为空,就利用私有的构造函数产生一个Singleton实例并把它赋值到singleton
*静态变量中
*/
if (singleton == null) {
singleton = new Singleton();
}
}
}
//如果不为空,就表示之前已经创建过实例,并将singleton当做返回值
return singleton;
}
public void add() {
System.out.println("add");
}
public static void main(String[] args) {
//创建实例
Singleton sing = Singleton.getSingleton();
Singleton sing2 = Singleton.getSingleton();
sing.add();
sing2.add();
//用“==”判断实例是否指向相同对象
System.out.println("sing == sing2: " + (sing == sing2));
}
}
运行结果:
add
add
sing == sing2: true //通过结果可以看出两个引用指向同一对象
复制代码
这是在同一个类中创建main()方法,如果在另外一个类中创建
public class Singleton {
private volatile static Singleton singleton;
private Singleton() {}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
public void add() {
System.out.println("add");
}
}
class MainTest {
public static void main(String[] args) {
/**
*语句不能通过编译,就保证了类的单一实例。
*/
//Singleton test3 = Singleton.singleton;
//getSingleton()方法时静态的,就可以在代码的任何地方使用Singleton.getSingleton()
Singleton test1 = Singleton.getSingleton();
Singleton test2 = Singleton.getSingleton();
//Singleton test4 = Singleton.singleton;
test1.add();
//test3.add();
System.out.println("test1 == test2: " + (test1 == test2));
//System.out.println("test3 == test4: " + (test3 == test4));
//System.out.println("test1 == test3: " + (test1 == test3));
//System.out.println("test1 == test4: " + (test1 == test4));
}
}
运行结果:
E:\test-git\Thread>javac Singleton.java
//编译时会编译出两个class文件,因为main方法在MainTest.class中,所有运行时用java MainTest
E:\test-git\Thread>java MainTest
add
test1 == test2: true
复制代码
“private volatile static Singleton singleton”中的private修饰符如果该为public就不能保证类的唯一实例。
public class Singleton {
public volatile static Singleton singleton;
private Singleton() {}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
public void add() {
System.out.println("add");
}
}
class MainTest {
public static void main(String[] args) {
Singleton test3 = Singleton.singleton;
//getSingleton()方法时静态的,就可以在代码的任何地方使用Singleton.getSingleton()
Singleton test1 = Singleton.getSingleton();
Singleton test2 = Singleton.getSingleton();
Singleton test4 = Singleton.singleton;
test1.add();
//test3.add(); 如果加上运行时会报异常,引用了空指针
System.out.println("test1 == test2: " + (test1 == test2));
System.out.println("test3 == test4: " + (test3 == test4));
System.out.println("test1 == test3: " + (test1 == test3));
System.out.println("test1 == test4: " + (test1 == test4));
}
}
运行结果:
add
test1 == test2: true // 从这看出test1和test2是指向同一个对象的
test3 == test4: false // 从下面三句可以看出test3和test1、test2、test4的引用不同。
test1 == test3: false //从“test3.add();”看出test3为null。
test1 == test4: true
复制代码
PS:我朋友说单例模式这才刚刚入门,还有两点更高级的东西,等进了水平高了再教。
作者:
pcy1022
时间:
2015-1-10 16:35
写得好,谢谢分享,收藏一下
作者:
Strong
时间:
2015-1-10 17:39
个人觉得单例模板和框架有点类似
作者:
执笔画梦
时间:
2015-1-10 17:45
有点复杂
作者:
Seejun
时间:
2015-1-10 23:10
已收藏,感谢分享
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2