设计模式是指软件开发人员面对一般问题的解决方案。
单例模式是指保证一个类仅有一个实例,并且提供一个全局访问方式的设计模式。
1 特点
1.1 优点
1.减少内存开销,尤其是频繁创建和销毁实例。
2.减少对资源的过多占用。
1.2 缺点
1. 没有抽象层,不能进行扩展(继承)。
2. 不适用于变化的对象。
3. 违背了“单一职责”原则,只重视内部关系,而忽略了外部关系。
4. 实例化后长期不适用,系统会默认为垃圾进行回收,造成对象丢失。
1.3 底层实现思路
1. 对本类构造方法私有化,防止外部调用构造放法创建对象。
2.创建全局唯一的对象,也做私有化处理。
3.通过自定义的公共方法将创建好的对象返回(类似封装属性后的getXxx())。
2 使用场景
1. 创建对象时占用过多的资源,同时又需要用到该类的对象。
2. 对系统内资源要求统一读写,如读写配置信息。
3. 当多个实例存在可能会引起程序逻辑错误,如号码生成器。
3 分类
3.1 饿汉式
饿汉式是指不管你用不用这个类的对象,都先给你创建这个类的对象。
package com.mh.design;
/*本类用于测试单例设计模式的饿汉式*/
public class Design {
public static void main(String[] args) {
//5.通过类名调用getSingle()方法获取本本类对象
MySingle single1 = MySingle.getSingle();
MySingle single2 = MySingle.getSingle();
//6.测试获取到的这两个引用类型变量是否相同
System.out.println(single1 == single2);//true
System.out.println(single1);//com.mh.design.MySingle@4554617c
System.out.println(single2);//com.mh.design.MySingle@4554617c
}
}
//1.创建自己的单例程序
class MySingle{
//2.提供构造方法,并且将构造方法私有化
private MySingle(){};
//3.在类的内部创建该类的对象,并且私有化
static private MySingle single = new MySingle();
//4.对外提供公共的访问方式
static public MySingle getSingle() {
return single;
}
}
3.2 懒汉式
懒汉式是指先不给你创建这个类的对象,等你需要用的时候再创建,利用了延迟加载的思想。
延迟加载思想是指不会在第一时间就把对象创建好来占用内存,而是什么时候用到,什么时候再去创建。
package com.mh.design;
/*本类用于测试单例设计模式的懒汉式*/
public class Design2 {
public static void main(String[] args) {
//4.创建对象并进行测试
MySingle2 s1 = MySingle2.getSingle2();
MySingle2 s2 = MySingle2.getSingle2();
System.out.println(s1 == s2);//true
System.out.println(s1);//com.mh.design.MySingle2@4554617c
System.out.println(s2);//com.mh.design.MySingle2@4554617c
}
}
//1.创建单例程序
class MySingle2{
//1.创建构造方法,并且私有化
MySingle2(){}
//2.创建引用类型的变量(延迟加载思想)
static private MySingle2 single2;
/*问题:程序中有共享资源single2,并且有多条语句(3句)操作了共享资源
* 此时single2共享资源在多线程环境下一定会存在多线程数据安全隐患
* 解决方案1:同步代码块[加锁,范围是操作共享资源的所有代码]
* 解决方案2:同步方法[如果方法中的所有代码都需要被同步,那么这个方法可以修饰成同步方法]
* 注意事项:锁对象在静态方法中,不可以使用this,因为静态资源优先于对象加载
* 锁对象可以使用外部创建好的唯一的锁对象o,但请注意,需要是静态的,静态只能调用静态
* */
//同步代码块中使用的唯一对象
static Object o = new Object();
//3.提供全局访问方式
//5.1 将方法修饰成同步方法
synchronized static public MySingle2 getSingle2() {
//5.2将可以操作共享资源的多条语句放入同步代码块中
synchronized (o){
if(single2 == null){
single2 = new MySingle2();//没有对象时才创建对象,并赋值给single2
}
return single2;//有对象则直接返回single2
}
}
}