首先我们看一下百度上面怎么解释的:
软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
其实简单点理解就是:
我们在开发中经常遇到一些问题,一个问题通常有很多种解法,但其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式
设计模式有20多种,对应20多种软件开发中会遇到的问题,下面说的单例模式是设计模式中的一种
单例模式是指在内存中只会创建且仅创建一次对象的设计模式。可以保证系统中,应用模式的这个类永远只有一个实例,即一个类永远只能创建一个对象,例如任务管理器对象我们只需要一个就可以解决问题了,这样可以节省内存空间。
下面我将讲述单例实际模式中常见的两种单例设计模式:
1.饿汉单例设计模式
2.懒汉单例设计模式
饿汉单例中类加载的方式是按需加载,且加载一次。因此,在上述单例类被加载时,就会实例化一个对象并交给自己的引用,供系统使用;而且,由于这个类在整个生命周期中只会被加载一次,因此只会创建一个实例,即能够充分保证单例,这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。简单点来说就是:你要的时候就有,未雨绸缪,不管你后面用没用到,都给你创建好了
优点是:快,只要你要用,就直接用,不会再创建
缺点是:浪费内存,你没要用的时候,它也创建了
下面是单例类代码如下
public class singleInstance {
//必须把构造器私有化,防止外界构造多个对象
private singleInstance(){}
//饿汉单例是在获取对象前,对象已经准备好了一个,这个对象只能是一个,所以定义静态变量记住
public static singleInstance instance = new singleInstance();
}
下面是测试类
public class Test {
public static void main(String[] args) {
singleInstance s1 = singleInstance.instance;
singleInstance s2 = singleInstance.instance;
System.out.println(s1 == s2); // 返回true,说明不管创建多少个对象,都是同一个
}
}
在外界都可以直接用类名.对象名调用,但是不管调用多少个,都只有一个,地址都是同一个,所以测试类中会输出true
设计步骤:
1.定义一个类,把构造器私有
2.定义一个静态变量存储一个对象
注意:如果不把构造器私有,那么在测试类中能创建很多对象,为避免这种情况,一定要将构造器私有,以免被外界调用
简单点来说就是非常懒,当你饿的时候才会创建,不像饿汉单例那样不管饿不饿已经做好了,随时来吃,而懒汉就是当你要用的时候,才会去创建
优点是:不浪费内存,想用就创建
缺点是:线性不安全,执行效率没有饿汉模式高
下面是单例类代码如下
public class singleInstance2 {
//私有化构造方法
private singleInstance2(){}
//定义一个静态成员变量负责存储一个对象,只加载一次,只有一份
//私有化,避免给别人挖坑
private static singleInstance2 instance;
//提供一个方法,对外返回单例对象
public static singleInstance2 getInstance(){
if(instance == null){
//第一次来拿对象,此时需要创建对象
instance = new singleInstance2();
}
return instance;
}
}
下面是测试类
public class Test {
public static void main(String[] args) {
singleInstance2 s1 = singleInstance2.getInstance();
singleInstance2 s2 = singleInstance2.getInstance();
System.out.println(s1 == s2); // 返回true,说明是同一个对象
}
}
我们从懒汉式单例可以看到,单例实例被延迟加载,即只有在真正使用的时候才会实例化一个对象并交给自己的引用。这种写法起到了懒加载的效果,但是只能在单线程下使用。如果在多线程下,一个线程进入了if(instance == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式。
设计步骤:
1.定义一个类,把构造器私有
2.定义一个静态变量存储一个对象
3.提供一个返回单例对象的方法