java是如何是实现单例模式的?
单例模式设计思路
1.单例模式,顾名思义是该类只有一个实例,当外部获取该类的对象时,都是获取同一个实例。
2.因此当外部使用构造方法new该类时,获取的都是同一个对象。显然想到这里,你觉得很难实现只有一个实例.
3.在这里单例模式使用了自身作为成员变量,来实现该方式,每次获取该类的实例,就获取该成员变量的一个实例。
4.同时要改造该构造方法,让外部new该类时,不能每次都实例化。这时候,我们类的实现是如下这样:
public class Singleton {
/**
* 自身作为成员变量.
*/
private Singleton singleton;
public Singleton() {
if(singleton == null) {
singleton = new Singleton();
}
}
}
5.这样你发现这个构造方法的逻辑不对,当成员变量为空时,就使用构造方法new一个该实例,但是这个构造方法已经变了,new该实例时,每次就重新调用该构造方法,一直调用.永远不能实例化,直至内存溢出。
6.也就是说该构造方法内部实例化的步骤不能改变,同时外部调用构造方法时,不能直接实例化,这里产生了矛盾。
7.内部调用构造方法时能够实例化,外面调用构造方法时不允许实例化。同一个方法实现两种情况。
8.那我们使用if{}else{}来判断,怎么判断是外部实例化和内部实例化呢?大家可以思考一下只改造构造方法的方式能实现单例模式吗?
9.那我们先采用两个方法实例化该对象,内部使用内部的构造方法,外部使用外部的构造方法。
10.新增一个方法newInstance()作为外部类调用的构造方法.外部调用该方法是必须是使用Singleton类调用该方法,而不是使用Singleton的对象来调用该方法。不然的话,我每次调用该方法时,都要先实例化Singleton类,那还要这个方法干嘛?因此该方法必须是公有的静态方法,Singleton类才能直接在其他类中直接调用该方法,而不用先实例化,实现如下:
public class Singleton {
/**
* 自身作为成员变量.
*/
private static Singleton singleton;
public Singleton() {
}
public static Singleton newInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
11.这样就实现了外部调用newInstance()时,都获取的同一个对象,由于该方法是静态的,所以它使用的成员变量singleton也必须是静态的,不然就语法错误。
12.还要考虑个问题,就是原先的public singleton() {}在外部也可以调用,外面可以调用该方法进行多次实例化,那么私有化该方法如下:priavate singleton() {},使得外部不能多次实例化。实现如下:
/**
* 单例模式~懒汉
*/
public class Singleton {
/**
* 自身作为成员变量.
*/
private static Singleton singleton;
private Singleton() {
}
public static Singleton newInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
13.这样我们就是实现了单例模式的懒汉模式。
14.由于在newIntance()实例化该类时,在最开始singleton == null的情况下,同时两个线程调用该方法时,singleton都是等于null,这样在多线程的情况下,就可能存在多例。因此懒汉模式的单例模式是线程不安全的,这样就有了保证线程安全的饿汉模式。实现如下:
/**
* 单例模式~饿汉
*/
public class Singleton {
/**
* 成员变量的实例化是在类加载的时候就实例化赋初值。因此在调用new Instance()时,
* singleton早已经实例化,不等于null
*/
private static Singleton singleton = new Singleton();
private Singleton() {
}
public static Singleton newInstance() {
return singleton;
}
}
15.回答上面那个问题,只改造构造方法的方式是实现不了的。欢迎评论。