单例模式(Singleton),顾名思义,就是一个类我在不管怎么生成对象的时候,都只有一个对象,如何确保一个类只有一个实例呢?我们知道,每个对象生成的时候,第一个肯定调用的是它的构造方法,所以我们可以在构造方法这里来入手,另外一个问题就是,一个类里面啥东东的归属是归属为类的本身而不是类所生成的对象呢?静态方法或者属性,对的,静态方法或者属性是属于类的,一般是Class.static变量或者属性等方式。看看下面的实现方式:
package com.java.designpattern;
public class SingleInstance {
public static void main(String[] args) {
SingleTon sigle = SingleTon.getInstance();
SingleTon sigle2 = SingleTon.getInstance();
System.out.println(sigle == sigle2);
Calendar cal = Calendar.getInstance();
}
}
/**
*
* @author bluesky
* 实现方式1 ,标准实现
*/
class SingleTon{
private static SingleTon single= new SingleTon();
public static SingleTon getInstance(){
return single;
}
private SingleTon() {
System.out.println("this is a demo for singleton");
}
}
/**
*
* @author bluesky
* 实现方式2, 一般不推荐
*/
class SingleTon2{
private static SingleTon2 single2;
public static SingleTon2 getInstance(){
if(null == single2){
single2 = new SingleTon2();
}else{
return single2;
}
}
private SingleTon2() {
System.out.println("this is a demo for singleton");
}
}
我们先看方法实现1.
private static SingleTon single= new SingleTon();
是个静态的变量,静态变量在对象初始化之前就会初始化然后保持不变,他会调用new SingleTon()函数,该函数是构造函数,特殊的地方是该构造函数是私有的,也就是说只有类内部调用,外面调用不到这个函数。
private SingleTon() {
System.out.println("this is a demo for singleton");
}
然后通过
public static SingleTon getInstance(){
return single;
}
返回具体的实例SgingleTon,这个也是静态的,在类对象初始化之前就初始化保持不变。
然后在生成实例的时候直接调用getInstance()就可以返回静态的single 对象了。如果直接new SingleTon就不行了,因为代码里面已经将他设置为私有(private)方式了。
打印结果如下:
this is a demo for singleton
true
说明两个问题:“构造'函数的确是只被初始化了一次;2. sigle == sigle2 表示生成的两个对象真的是完全相等的。
再看看实现方式2,其实一般情况下也可以生成单个对象,但是一般情况下不推荐,主要在多线程中有风险:
if(null == single2){
single2 = new SingleTon2();
}else{
return single2;
}
<pre name="code" class="java"> return single2;
这里做了个判断,如果single2 为空的时候会去new一个对象,否则会返回之前生成的对象。正常情况下都没问题,但是如果再多线程中,当第一个线程走到:
if(null == single2){
然后因为时间片调度休眠了,第二个线程走到:
if(null == single2){
发现这个的确为空,然后就会执行:
single2 = new SingleTon2();
并返回。然后时间片调度又回到线程1,线程1苏醒,从刚刚睡的地方开始接着往下执行:
single2 = new SingleTon2();
又生成了一个对象,显然,两次对象生成肯定是不一样的,这样返回去的就不是一个单例了。所以在多线程中就需要加个sysnchronized的关键字来保证互斥。明显要麻烦了。所以一般情况下就用方法1.也是当前比较通用的做法。