JAVA单例模式I 饿汉式 懒汉式 学习笔记

单例模式 Singleton Model

熟悉JAVA类加载的同学一定知道JAVA中每次通过new关键字实例化对象这种操作会在我们的JAVA常量池中Heap区域申请一片区域内存,如果大量使用对象实例化操作来调用对象对于计算机的内存无疑是一种浪费。所以为了解决这种浪费使用单例模式来解决Heap OverFlower虽然JAVA中有GC机制(垃圾回收机制)但是避免不了的是Heap区和常量池的浪费对于程序运行的效率影响。所以单例模式的出现可以在一定程度上解决内存和常量池的浪费。

单利模式是什么

单例模式就是让我们想要调用的方法类只会在java 内存存在一个 保证他的唯一性的一种书写方法。这样的话就可以节省实例化对象的时间并且节省new对象产生的内存防止大量实例化对象产生的内存溢出【虽然现在的计算机都比较厉害但是本着精中求精的精神还是学习下设计模式的好】

但是单例模式中饿汉式懒汉式是比较常用的模式所以就先谈一谈这两种设计模式。双重检测锁、 内部静态类 枚举 会在下一篇博客中分享。


饿汉式:

饿汉式的单例模式是直接就在内部将自身实例化所以返回的方法就一定是单例的类

public class Singleton 
{
//实例化一个私有的静态Singleton类
private static Singleton singleton = new Singleton();
//私有化无参构造器(好处是其他类无法调用并且对Singleton 进行实例化操作)
private Singleton(){}
public static Singleton getSingleton ()
{
//没有判断该Singleton 类是否被实例化返回已经创建好的Singleton 类
return singleton ;
}	
public void print (){//只是随便输出一个字符串当做测试代码无实际作用
System.out.println("Hello this a Singleton class"); 
}

} 
public class test
{
public static void main(String[ ] args) { 
//可以创建一个Singleton 类型的singleton 进行保存实例化后的Singleton 类
Singleton singleton =Singleton.getSingleton ();
//然后在通过singleton 调用print();方法
singleton.print();
//也可以直接调用通过getSingleton();调用print();方法
Singleton.getSingleton ().print ();
}

饿汉式先把Singleton 类无参构造方法私有,这样别人就无法用通常方法从外部对Singleton 类进行实例化。除非使用反射、克隆、反序列化进行实例化Singleton类。Singleton类加载把自己实例化对象放在了java静态池中,然后就可以直接调用静态的getSingleton ();方法,返回实例化后的Singleton 类就可以调用到这个实例化后的单例方法。因为每次调用单例方法都是该类已经实例化后的Singleton 类;这样有一个好处就是比较浪费静态池的空间。所以一般用在需要实例化很多次的类中因为需要多次调用所以使用懒汉式这种用空间换取调用速度的单例方法。


懒汉式:

懒汉式是等确定对象是否被实例化如果没有被实例化就进行实例化操作如果已经实例化了直接返回实例化后的该类


public class Singleton 
{
//创建一个私有的静态Singleton类型等待赋值
private static Singleton singleton = null;
//私有化无参构造器
private static Singleton(){}
public static Singleton getSingleton ()
{
If(singleton == null){//判断Singleton是否被实例化过如果没被实例化过
singleton = new  Singleton ();//在此处进行实例化操作
//注意!现在singleton变量已经是实例化后的Singleton 类
return singleton ;//并且返回一个已经被实例化后的Singleton类
}else{ //如果singleton 已经被实例化
return singleton ;//返回该实例
}
}
} 
public class test
{
public static void main(String[ ] args) { 
//可以创建一个Singleton 类型的singleton 进行保存实例化后的Singleton 类
Singleton singleton =Singleton.getSingleton ();
//然后在通过singleton 调用print();方法
singleton.print();
//也可以直接调用通过getSingleton();调用print();方法
Singleton.getSingleton ().print ();
}
}

懒汉式和饿汉式相同先把Singleton 类私有这样别人就无法从外部对Singleton 类进行实例化但和懒汉式不同的是懒汉式在执行getSingleton ()方法判断Singleton 类没有被实例化后才进行实例化,如果有被实例化就直接返回已经实例化后的Singleton 类,当然会可能有线程安全问题所以可以再getSingleton ()方法上加线程锁来解决。在调用getSingleton ()方法后才进行实例化的懒汉式的好处就是因为只有在调用该方法才进行实例化这样减少静态池内存占用但是new实例在JAVA中比较耗费时间。



饿汉式与懒汉式比较:

在开发中如果我需要一个Singleton类的方法

内存与时间比

如果用饿汉式写在一开始就已经对Singleton 类进行实例化操作在静态域中申请一片空间,这样有一个好处就是占用空间但是执行效率要高但是如果我没有用到这个Singleton方法的话申请的一片我们java中宝贵静态池的内存就白白的浪费掉了。

那么节省内存的方法就是使用懒汉式因为只有在需要Singleton类实力的时候才进行实例化这种方式毫无疑问是浪费事件的方法

所以饿汉式是用内存换取时间的方法懒汉式是用时间换取内存的方法


线程安全问题:

饿汉式是不会有线程安全问题的但是懒汉式因为是在方法体中实例化单例类所以会有此项问题虽然使用线程锁可以解决掉此项问题但是调用线程锁势必会对执行效率进行影响。


单例模式 II 双重检测锁 内部静态类 枚举 学习笔记


你可能感兴趣的:(JAVA设计模式)