java设计模式--单例模式
一:单例模式定义:
单例模式:一个类只创建一个对象,并且提供一个其他类访问该对象的点。
这样说有些抽象,其实就是这个类的构造函数设置为私有的,然后提供一个方法以便于共用该类的一个对象。
下面简单介绍一下单例模式的几种实现方式以及优缺点
二:单例模式的实现:
1、类加载的时候new一个单例对象
package MM;
public class Sington {
private Sington() {}
private static Sington sington = new Sington();
public static Sington getSingleObject() {
return sington;
}
}
优点:实现简单,便于理解
缺点::每次类在加载的时候都会新建一个对象,造成内存和cpu的浪费
2,调用函数判断是否存在对象
package MM;
public class Sington {
private Sington() {}
private static Sington sington;
public static Sington getSingleObject() {
if (sington == null) {
sington = new Sington();
return sington;
}
else return sington;
}
}
优点:可以避免每次类加载的时候创建对象,节省资源。
缺点::在多个线程访问该类的对象的时候可能同时产生不止一个对象,造成错误。
3,静态内部类创建一个单例对象
package MM;
public class Sington {
private Sington() {}
private static class InnerClass{
private static Sington sington = new Sington();
}
public static Sington getSingleObject() {
return InnerClass.sington;
}
}
优点:可以满足大部分场景的需求,不会产生多余的对象。
缺点::实现复杂,难于理解。要明白类加载机制。
4,线程锁创建对象
package MM;
public class Sington {
private Sington() {}
private static Sington sington;
public synchronized static Sington getSingleObject() {
if (sington == null) {
sington = new Sington();
return sington;
}
else return sington;
}
}
优点:实现简单,能够实现单例模式的需求。
缺点::当有多个线程访问这个类的对象的时候,并发操作可能会降低cpu的利用率,造成资源的浪费。
5,代码锁(双重校验)创建对象
package MM;
public class Sington {
private Sington() {}
private static Sington sington;
public static Sington getSingleObject() {
if (sington == null) {
synchronized (Sington.class) { // 锁住这个类的该方法,等同于this
if (sington == null) {
sington = new Sington();
}
}
}
return sington;
}
}
优点:能够提高并发的效率,满足大部分场景的需求。
缺点::实现复杂,逻辑复杂。
三:单例模式的总结:
单例模式是一种比较重要的设计思想,这里我们主要说一下单例模式实现时候的注意事项。
1:首先要明确,私有构造函数并不是只能创建一个对象,是只有本类才能创建这个类的对象,其他的类引入
这个类并不能创建该类的对象,甚至是一个包下的也不可以。所以这个类需要提供一个访问这个类的静态函数。
(访问这个类即得到的这个类的对象)。
2:第三种静态内部类实现单例模式,并不会产生多个对象,首先,静态内部类在main函数启动的时候并不会加载,
只有访问静态内部类的静态域(静态变量)或者静态方法的时候才会加载这个类,而且在只有一个类加载器的情况下,
类只会被加载一次,所以只会产生一个对象。
3:静态内部类的加载顺序在我的其他博客中有详细介绍和代码演示:java静态内部类加载顺序