以往我们创建一个java类后,可以通过这个类创建多个对象,但是有时候我们需要确保某个类只有唯一的实例对象,在应用程序的各个地方都是调用的这个唯一的对象。

使用new关键字创建对象时会调用类的构造方法,那么能够阻止程序员创建对象的唯一方法是把构造方法设置成私有的
我们可以试一下,首先创建一个SingleTon类,代码如下:
public class SingleTon {
 private SingleTon(){
 }
}
这个类由于构造方法是私有的,所以不能在外面使用new关键字来创建对象
但是离我们的需求还差点,我们得留个口子让程序员能够创建一个唯一的对象,此时我们可以创建一个方法,用于返回一个对象。

 public SingleTon getInstance(){
    return new SingleTon();
 }

private修饰过的方法不能在外面调用,但是在本类中可以调用,所以在这里new了一个本类对象,然后返回出去。
这里又出现了两个问题:
1,这个方法属于类对象的方法,只能通过对象来调用,但是现在我们没法用构造方法来创建对象,还怎么调用呢?这就是鸡和蛋的问题了。
2,这个方法每次被调用时都会new一个新的对象,肯定是不符合我们的需求的。

首先,我们可以使用static关键字来修饰这个方法,让这个方法可以被类来直接调用,所以就变成如下:
 public static SingleTon getInstance(){
    return new SingleTon();
 }
然后这个方法里面肯定不能每次new一个对象了。
我们可以在类中定义一个类的对象,然后每次调用getInstance()方法时返回这个对象,那么以后得到的每个对象不都永远是唯一的那个么.
所以最终代码如下:
public class SingleTon {
private static SingleTon singleTon=new SingleTon();
    private SingleTon(){
    System.out.println("构造方法");
    }
    public static SingleTon getInstance(){
    return singleTon;
    }
public void sayHello(){
System.out.println("hello");
}
}
singleTon会在SingleTon类加载时new出来,以后再不会new了。
这里之所以要把singleTon这个变量修饰为static,有两个考虑:
1,getInstance()方法是static的,里面不能引用本类其他的非static的成员变量。
2,static的变量是静态变量,可以让singleTon这个变量的状态在应用程序中得以保存,相当于一个全局的变量,那么我们
   用静态方法返回时就返回的是同一个对象。
   这是单例模式的第一种写法。

单例模式的另外一种写法是:在类中只声明一个本类对象,在调用方法的时候才创建对象。
public class SingleTon {
private static SingleTon singleTon;
private SingleTon(){
System.out.println("构造方法");
}
public static SingleTon getInstance(){
if(singleTon==null){
        System.out.println("执行创建对象");
        singleTon=new SingleTon();
}
return singleTon;
}
}
当第一次调用getInstance()方法的时候,singleTon肯定等于null,所以会进去new一个对象;再次调用getInstance()方法时,singleTon就不等于null了,直接被返回。
这种写法在多线程程序里面是有隐患的,有可能会出现创建多个对象的情况。
假如说现在有两个线程,线程A和线程B。这两个线程都来调用getInstance()方法,线程A在判断singleTon等于null后,进入if语句,此时线程B也赶来判断singleTon是否等于null,很显然,当线程A没有执行到singleTon=new SingleTon();这一步时,线程B也会判断通过,然后进入if语句进行对象的创建。那么这种情况就会导致创建两次对象,这并不符合我们的需求。
为了避免这种情况,我们可以在getInstance()方法上同步锁关键字:synchronized,让这个方法同时只能被一个线程访问,所以最终的代码如下:
public class SingleTon {
private static SingleTon singleTon;
private SingleTon(){
System.out.println("构造方法");
}
public synchronized  static SingleTon getInstance(){
if(singleTon==null){
        System.out.println("执行创建对象");
        singleTon=new SingleTon();
}
return singleTon;
}
}