设计模式之单例模式
来源:互联网 发布:windows压力测试工具 编辑:程序博客网 时间:2024/06/14 01:54
出处:http://blog.csdn.net/jesson20121020
单例模式也是创建模式中的一种。
单例模式:
所谓的单例模式,即单一的实例,保证类在内在中只有一个对象。
举例: windows的打印服务,网络计数器
应用: 线程池,数据库连接池,Runtime
如何保证类在内存中只有一个对象?
1. 将构造方法私有化,为了不让外界创建对象
2. 在类中创建一个对象
3. 通过一个公共的访问方法给外界提供一个入口。
按照这个步骤,我们可以保证类在内存中只有一个对象,但这里有个问题,就是在第二步“在类中创建对象”时,选择什么时候创建对象,是选择在类加载时创建还是在外界需要时创建呢??这里也就引出了单例模式的两种类型,饿汉式和懒汉式,分别如下:
两种类型的单例模式:
1. 饿汉式
顾名思义,也就是在类加载时就创建对象,在外界访问时直接通过上述第三步中提供的访问入口访问,而不需再创建。如下例:
Student.java
- public class Student {
- //1. 为了不让外界访问,我们把构造方法私有化
- private Student(){
- }
- //2. 创建一个对象
- //为了满足静态方法访问,这里也必须加一个静态修饰符。
- //为了不让外界修改s对象,需要在将s私有化,即加私有修饰符private
- private static Student s = new Student();
- //3. 提供一个公共的访问方法
- //为了让外界直接访问,我们需要给该方法加一个静态修饰符。
- public static Student getStudent(){
- return s;
- }
- public void show(){
- System.out.println("我要学好设计模式");
- }
- }
StudentTest.java
- public class StudentTest {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- //下面实质是创建了两个类
- /*Student s1 = new Student();
- Student s2 = new Student();
- System.out.println(s1 == s2);*/
- Student s1 = Student.getStudent();
- Student s2 = Student.getStudent();
- System.out.println(s1 == s2);
- s1.show();
- s2.show();
- }
- }
综上所述,饿汉式单例模式是在类加载时就创建对象,即private static Student s = new Student();相应地,在外界需要时创建对象就是懒汉式了,如下。
2. 懒汉式
延迟加载思想:我们什么时候需要,你就什么时候给。(eg. Hibernate)
也就是说在外界需要的时候创建对象,并且保证类在内存中只有一个,如下例:
Teacher.java
- <span style="font-size:12px;">public class Teacher {
- //为了不让外界创建对象,将构造方法私有
- public Teacher() {
- // TODO Auto-generated constructor stub
- }
- //本类创建一个对象,注意,在这里不能new Teacher(),否则就成饿汉式了
- //这里加static是为了保证静态方法可以访问
- //这里加private是为了保证外界不能直接访问
- private static Teacher t = null;
- //提供公共的访问方法
- public static Teacher getTeacher(){
- if(t == null)
- t = new Teacher();
- return t;
- }
- public void show(){
- System.out.println("我要教好设计模式");
- }
- }</span>
TeacherTest.java
- <span style="font-size:12px;">public class TeacherTest {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- Teacher t1 = Teacher.getTeacher();
- Teacher t2 = Teacher.getTeacher();
- System.out.println(t1 == t2); //true
- t1.show();
- t2.show();
- }
- }
- </span>
可以很容易看出,懒汉式单例模式不仅保证了在内存中只有一个类,而且是在需要的时候创建对象,而不像饿汉式那样,在类加载的时候就创建。
在了解了两种类型的单例模式后,就有一个问题了,在实际的开发和面试中到底选择哪一个呢???
在开发中应该选择哪个单例模式??
一般我们开发中采用第一种方法,也就是说饿汉式。
原因:
多线程安全问题。饿汉式不存在线程安全问题,而懒汉式存在线程安全问题。
具体解释:
在饿汉式的例子中,当有多个线程访问时,比如说有t1和t2同时访问getStudent()时,因为Student 对象是在类一开始加载时就已经创建好的,所以它们不管谁返回都是同一个对象,都是一开始已经创建好的对象,所以不存在线程安全问题。
在懒汉式的例子中,当有有多个线程访问时,比如有t1和t2同时访问getStudent()时,这个时候,当t1进来后判断这个时候t=null ,所以t1就进去执行if所控制的语句,但是注意了,由于线程的随机性,可能t1刚进去要执行if控制语句,这个时候,被t2抢到了cpu的执行权,这个时候,t2开始执行了,发现,这个时候t还是null,所以t2也进去执行if所控制的语句了,那么将来会有多个对象被创建,因此懒汉式存在线程安全问题。
因此,在开发中我们一般选择不存在线程安全问题的饿汉式单例模式。
在面试中一般会选择哪种单例模式??
在面试中,一般会选择懒汉式单例模式,而且主要是面试以下几个问题:
A: 延迟加载思想
B: 线程安全问题
a: 线程安全问题是怎么产生的??
b: 线程安全问题是如何解决的??
---在存在线程安全问题地方加同步关键字"synchronized"。
因为被同步的代码,在某一个时刻只能被一个线程访问。
因此,可以在getTeacher()方法处加入同步关键字"synchronized",以解决懒汉式存在的线程安全问题。
其实,在JDK中,已经有单例模式的应用了,就是Runtime类,而且是饿汉式单例模式。如下:
- <span style="font-size:12px;">public class Runtime {
- private static Runtime currentRuntime = new Runtime();
- public static Runtime getRuntime() {
- return currentRuntime;
- }
- private Runtime() {}
- }</span>
- 设计模式之 单例设计模式
- 设计模式之 单例设计模式
- 设计模式之单例设计模式
- 设计模式之-----------单例设计模式
- 设计模式之:单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之-单例设计模式
- 设计模式之单例设计模式 标签: 设计模式
- 设计模式之单例
- 设计模式之单例
- 设计模式之 单例
- 【我参加过的】PHP面试题之数组的应用
- 自己实现strchr函数
- 自己实现strcat函数
- 网络安全
- 文件系统安全
- 设计模式之单例模式
- Charbase
- SQL SERVER 转出数据到 Access
- 【转载】HTTP 状态代码
- 【转载】Django model字段类型清单
- swift 字符串小记
- 回调的原理实现与应用
- swift UILabel小记
- 【new Date(str)】IE这个SB浏览器