单例设计模式
1、 概 念
目的:确保类在内存中只有一个对象
该实例必须自动创建,且对外提供
2、代 码
2.1 饿汉式
Student.java
package com.monkey1026; public class Student { // 1、构造私有 private Student() { } //2、 自己造一个 // 静态方法只能访问静态成员变量,加静态 // 为了不让外界直接访问修改这个值,加private private static Student s = new Student(); // 3、提供公共的访问方式 // 为了保证外界能够直接使用该方法,加静态 public static Student getStudent() { return s; } }
StudentDemo.java
/* * 单例模式:保证类在内存中只有一个对象。 * * 如何保证类在内存中只有一个对象呢? * A:把构造方法私有 * B:在成员位置自己创建一个对象 * C:通过一个公共的方法提供访问 */ public class StudentDemo { public static void main(String[] args) { // 通过单例如何得到对象呢? // 直接调用静态的getStudent()方法 Student s1 = Student.getStudent(); Student s2 = Student.getStudent(); System.out.println(s1 == s2); System.out.println(s1); System.out.println(s2); } }
结果:
true com.monkey1026.Student@7852e922 com.monkey1026.Student@7852e922
为什么叫 饿汉式?
private static Student s = new Student();
这行代码随着类的加载 而 加载(立马创建了Student对象)! static静态
2.2 懒汉式
Teacher.java
package com.monkey1026; // 懒汉式 public class Teacher { // 1、提供私有构造方法 private Teacher() { } // 2、 private static Teacher t = null; // 3、提供公有访问 public synchronized static Teacher getTeacher() { // 懒汉式 在多线程环境下存在线程安全问题,所有 必须加synchronized,同步方法 程序才会正确!!! if (t == null) { t = new Teacher(); } return t; } }
TeacherDemo.java
package com.monkey1026; public class TeacherDemo { public static void main(String[] args) { Teacher t1 = Teacher.getTeacher(); Teacher t2 = Teacher.getTeacher(); System.out.println(t1 == t2); System.out.println(t1); System.out.println(t2); } }
结果:
true com.monkey1026.Teacher@7852e922 com.monkey1026.Teacher@7852e922
3、 饿汉式 和 懒汉式 的比较:
单例模式中:
饿汉式: 类一加载就创建对象
懒汉式: 用的时候,才去创建对象
面试题:单例模式的思想是什么? 请写一个代码体现。
开发时: 饿汉式 (是不会出问题的单例模式)
面试时: 懒汉式 (可能会出问题的单例模式)
A: 懒加载(延迟加载)
B: 线程安全问题 所以必须使用synchronized
a:是否多线程环境 --- 是
b:是否有共享数据 --- 是
c:是否有多条语句操作共享数据 ---是
扩展:
Runtime类 : 每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。
JDK中的 Runtime类 的设计 就是采用 饿汉式的单例设计模式
查看源码:
class Runtime { private Runtime() {} private static Runtime currentRuntime = new Runtime(); public static Runtime getRuntime() { return currentRuntime; } }
好玩的方法:
exec ( String command ) -调用dos命令
代码:
package com.monkey1026; import java.io.IOException; public class RuntimeTest { public static void main(String[] args) throws IOException { // 获取对象 Runtime r = Runtime.getRuntime(); // 调用方法 exec(String command) // r.exec("notepad"); //打开记事本 r.exec("calc"); //打开计算器 } }
结果: 会打开计算器