------- android培训、java培训、期待与您交流! ----------
单例设计模式
第一部分:
1、设计模式的概念:
每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次有一次地使用该方案而不必做重复劳动;而模式就是解决某一类问题最行之有效的方案;这是一个纯粹偏思想的,在不断的劳动的过程中总结出来的。2、设计模式的特点:
2.1、将某一类问题解决起来会变的更简单;2.2、让复杂的问题简单化;
3、单例设计模式:
解决一个类在内存中存在一个对象;换句话说就是在一个类中只能有一个对象,不可能会出现第二个对象;4、单例设计模式的由来:
现在有两个程序,分别是A程序和B程序,当A程序要操作一个文件的时候,这是就要new一个对象,当B文件也要操作一个文件的时候,同样也要new一个新的对象,但是A和B操作的不是同一个对象,因此这时要保证对象的唯一性;
5、单例设计模式的思想:
5.1、为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象;5.2、禁止其他的程序建立对象,由自己来建立对象;5.3、为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象;5.4、为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式;6、单例设计模式的步骤:
6.1、将构造函数进行私有化;6.2、在类中创建一个本类对象;6.3、提供一个方法可以获取到该对象;7、代码表现:
<span style="font-size:18px;">class Single { private int num; public void setNum(int num) { this.num = num; } public int getNum() { return num; } // 将构造函数进行私有化; private Single(){} // 创建一个本类对象; private static Single s = new Single(); // 返回的是一个Single类型的对象; public static Single getInstance()//一个类类型的 { return s; } } class SingleDemo { public static void main(String[] args) { // 类名调用静态方法 Single s1 = Single.getInstance(); Single s2 = Single.getInstance(); // Single s1 = new Single(); // Single s2 = new Single(); s1.setNum(30); System.out.println(s2.getNum()); // Single ss =Single.getInstance(); } } /* 打印的是30,说明s1 和s2 指向的是同一个对象 */</span><span style="font-size:24px;font-weight: bold;"> </span>
8、运行的结果:
设置的是s1的值是30,而打印的是s2的值也是30,由此可以s1和s2所指向的是同一个对象;
9、图形展示:
10、单例设计模式应用:
对于事物该怎么描述,还是怎么描述,当需要将该事物的对象保证在内存中唯一性时,就加入单例设计模式思想即可;
举例:
class Student { private int age;//要将属性进行私有化 public void setAge(int age) { this.age = age; } public int getAge() { return age; } // 要求保证在内存中的唯一性,那么就加上下面的三步 private Student(){} private static Student s = new Student(); public static Student getInstance() { return s; } } class SingleStudentDemo { public static void main(String[] args) { // 调用静态方法; Student s1 = Student.getInstance(); Student s2 = Student.getInstance(); s1.setAge(34); System.out.println(s2.getAge()); } }
运行后的结果:
第二部分:
1、饿汉式
先初始化对象,开发一般会用饿汉式
2、饿汉式特点
2.1、Single类进内存,对象还没有存在,就已经创建好了对象;2.1、安全,简单;3.饿汉式代码体现
<span style="font-size:14px;">//第一种,这个是先初始化对象 //称为:饿汉式 class Single { private Single(){} private static Single s = new Single(); public static Single getInstance() { return s; } }</span>
4、懒汉式
对象是方法被调用时,才初始化,也就做对象的延时加载;
5、延时加载
特点:Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象;
6、懒汉式的特点
刚开始不建立对象,如果什么时候需要,那么就什么时候建立对象;
7、懒汉式代码体现
//第二种,对象是方法调用时,才初始化,也叫做对象的延时加载,称为懒汉式 class Single { private Single(){} private static Single s =null; public static Single getInstance() { if(s==null) { synchronized(Single.class) { if(s==null) s = new Single(); } } return s; } } class SingleDemo { public static void main(String[] args) { Single ss = Single.getInstance(); } }
8、懒汉式的缺陷
8.1、缺陷:
如果遇到多线程时,当A程序读到getInstance的方法的时候,当cpu执行到s==null时,但是这时cpu切换到去处理B程序了,但是这时A程序就处于休息状态,没有执行程序,但是这时B程序同样也进来了,判断了s==null也是满足条件的,现在A程序醒了,然后执行了s = new Single();创建了一个对象,这是B程序也醒了,又创建了一个对象;换句话说就是现在内存中的对象已经不唯一了,懒汉式在多线程访问时会出现安全隐患;
8.2、措施:
在函数上加上一个锁就是Synchronized,这时如果A程序进来之后,但是B程序就不可以进入程序了,A程序创建了对象之后,然后返回了,这时B程序判断s已经不等于null,那么就不再执行程序了。但是在这个锁加载函数上面,每一个线程都要先进行判断一下,效率比较低效;这时如何能够既能可以保证对象的唯一性又能解决低效的问题?用双重判断来解决:判断锁的次数减少了;
9、面试
9.1、问:懒汉式和饿汉式有什么不同?
答:懒汉式的特点在于实例的延时加载。9.2、问:懒汉式的延迟加载有没有问题?
答:有,如果多线程访问时,会出现安全问题。
9.3、问:出现了安全问题怎么解决?
答:可以加同步来解决,而加同步的方式有两种,同步代码快和同步函数都行,但是稍微有些低效,用双重判断的形式可以解决效率的问题。
9.4、问:加同步的时候使用的锁是哪一个?
答:该类所属的字节码文件对象。
第三部分
我的总结:
1、定义单例的时候建议使用饿汉式,因为饿汉式不会出问题,简单安全;2、使用单例延时加载的时候,保证对象的唯一性,以及用双重判断来提高效率;3、饿汉式的特点:对象先进行初始化;懒汉式的特点:对象后进行初始化;4、懒汉式如何在多线程访问时解决安全隐患。5、懒汉式的面试题;