<big>版权声明:本文为 Codeagles 原创文章,可以随意转载,但必须在明确位置注明出处!!!</big>
单例设计模式
- 什么是单例设计模式?
所谓的单例设计指的是一个类只允许产生一个实例化对象。
我们来看单例设计模式是如何一步一步演化过来的。
Talk is cheap, show me the code.
public class SingletonTest {
public static void main(String[] args) {
Singleton s= null;
s=new Singleton();
s.print();
}
}
class Singleton{
public Singleton(){}
public void print(){
System.out.println("Hello World");
}
}
对于这段代码,很简单都不陌生,就是创建Singleton类,然后在另一个类中去实例化对象调用print方法,最后输出Hello World。原因是因为当我们在SingletonTest中实例化了对象的时候调用了Singleton类中的无参的构造方法,接下来结果就不足为奇了。
public class SingletonTest {
public static void main(String[] args) {
Singleton s= null;
s=new Singleton();//报错
s.print();
}
}
class Singleton{
private Singleton(){}//私有构造方法
public void print(){
System.out.println("Hello World");
}
}
那么对于上述代码,进行改造,将构造方法的public改为private,那么上述代码就会报错,因为实例化的时候,构造方法被私有,表示该类不能被外部进行实例化对象,那么如何解决这个问题,我们继续看改造代码。
public class SingletonTest {
public static void main(String[] args) {
Singleton s= null;
s=Singleton.instance;//②
s.print();
}
}
class Singleton{
static Singleton instance = new Singleton();//①
private Singleton(){}//私有构造方法
public void print(){
System.out.println("Hello World");
}
}
为了解决外部不能实例化对象的问题,那么就在内部进行实例化对象,加上Singleton instance = new Singleton();
那么就可以解决这个问题,但是在内部是解决了,外部依然无法调用print方法啊,因为外部没有对象,所以我们想到用static关键字,例如①所示,然后在SingletonTest中如②直接类.对象
来创建新对象,再去调用print方法,问题搞定了。
那么新的问题来了,以上虽然取得了Singleton类的实例化对象,但是对于类中的属性应该用private
进行封装,想要访问封装属性知道需要提供getter
方法,那么我们需要在①的前面加上private static Singleton instance = new Singleton();
不过此时访问的是static
属性,并且这个类无法在外部进行实例化对象创建,所以再提供一个static
方法,因为static
方法不受实例化控制。那么改造的代码如下:
public class SingletonTest {
public static void main(String[] args) {
public static void main(String[] args) {
Singleton s= null;
s=Singleton.getInstance();//获取实例化对象
//s1=Singleton.getInstance();//获取实例化对象
//s2=Singleton.getInstance();//获取实例化对象
s.print();
}
}
}
class Singleton{
private static Singleton instance = new Singleton();//加上private
//提供static方法,用来获取实例化对象
public static Singleton getInstance(){
return instance;
}
private Singleton(){}//私有构造方法
public void print(){
System.out.println("Hello World");
}
}
对于上述代码,在Singleton类中,提供了获取实例化对象的静态方法,也将属性进行了私有化,那么在SingletonTest中无论获取多少个对象,实际上都是同一个对象,因为类加载的时候已经实例化了一次对象,这就是单例设计模式。
扩展
对于单例设计模式,还有两种类型:
- 饿汉式
- 懒汉式
饿汉式
既然是饿汉式,我们就要在整体之中,只能有一个实例化对象,所以一般在原基础上还会为其增加final关键字。这个没有什么分析的问题。
class Singleton{
private final static Singleton INSTANCE = new Singleton();//加上final
//提供static方法,用来获取实例化对象
public static Singleton getInstance(){
return INSTANCE;
}
private Singleton(){}//私有构造方法
public void print(){
System.out.println("Hello World");
}
}
对于代码改造就是一点,其他的都不变,这就是饿汉式。
懒汉式
所谓懒汉式,是指第一次去使用Singleton类对象的时候,才会为其进行实例化处理操作。
class Singleton{
private static Singleton instance;//不需要再去实例化
public static Singleton getInstance(){
if(instance==null){//表示此时还没有实例化对象
instance=new Singleton();
}
return instance;
}
private Singleton(){}//私有构造方法
public void print(){
System.out.println("Hello World");
}
}
这就是懒汉式,当然这个设计模式在后续多线程等部分会有性能问题,以后我们在进行讨论。
对于单例的使用场景,比如windows中的回收站就是一个例子,不管是在C,D,E盘那个盘符中,都会有一个隐藏的回收站文件夹,将文件放入到该文件夹后,再回到桌面上打开回收站发现文件在里面,说明不论在哪,整个系统只有一个回收站,这就是典型的单例设计。
以上就是单例设计模式,一步一步在最基础的代码中,演化出来的。