单例设计模式
- 设计模式介绍与代码编写
在编写程序时经常会遇到一些典型的问题或需要完成某种特定需求.设计模式就是针对这些问题和需求.在大量的实践中总结和理论化之后的代码结构.编程风格以及解决问题的思考方式.设计模式就像经典的棋局. 不同的棋谱,我们用不同的棋局.免得自己再去思考和摸索.
单例模式是Java中的一种设计模式,它是指在设计一个类时,需要保证在整个程序运行期间针对该类只存在一个实例对象. 作用: 限制对象的创建.
问题1 : 对象中到底有什么 ? 属性(存储数据) , 行为(操作数据).
问题2 : 程序中为什么要限定的对象的创建呢 ?
- class SingleDemo
- {
- public static void main(String[] args)
- {
- Singleton s1 = Singleton.getInstance();
- Singleton s2 = Singleton.getInstance();
- boolean result = s1 == s2;
- System.out.println("result="+result);
- /*
- Singleton s1 = new Singleton();
- Singleton s2 = new Singleton();
- boolean result = s1 == s2;
- System.out.println("result="+result);
- */
- }
- }
- // 定义一个单例类
- class Singleton
- {
- // 1. 自己创建一个对象
- // 静态变量特点: 内存中仅有一份,能够被该类的所有实例对象所共享.
- private static Singleton INSTANCE = new Single();
- // 2. 构造方法 (私有化)
- private Singleton()
- {
- }
- // 3. 提供一个返回该对象的静态方法
- public static Singleton getInstance()
- {
- return INSTANCE; // 返回自己在本类中创建好的实例对象
- }
- }
从运行结果可以看出.变量 s1 和 s2 值相等.这说明变量 s1 和 s2 引用同一个对象.也就是说两次调用 getInstance() 方法获得的是同一个对象.而 getInstance() 方法是获得 Single 实例对象的唯一途径.因此 Single 类是一个单例的类.
2. 单例设计模式具备如下特点 :
1. 类中的构造方法使用 private 关键字修饰,声明为私有.这样就不能在类的外部使用 new 关键字来创建实例对象了.
- 在类的内部创建一个该类的实例对象,并使用静态变量 INSTANCE 引用该对象,由于变量应该禁止外界直接访问,因此使用 private 修饰.声明为私有成员.
- 为了让类的外部能够获取类的实例对象,需要定义个静态方法 getInstance (); 用于返回该类实例 INSTANCE, 由于方法是静态的.外界可以通过 "类名.方法名();" 的方法来访问. -> Single.getInstance();
3. 多学一招 : final单例 :
特点: 单例实现的两步曲.
单例模式也可以写成如下形式 : 使用 final 修饰可以实现. 但是如果提供一个公共方法,那么方法内部还可以做一些逻辑判断.
- /*
- 多学一招 : 两步实现单例设计模式
- 1. 私有化构造方法
- 2. 在本类的内部创建一个对象,使用public修饰,并静态化该变量,
- 并需要使用 final 关键字对INSTANCE变量进行最终化,表示该变量不能够再次被修改.
- */
- class Demo
- {
- public static void main(String[] args)
- {
- // 根据Single类创建对象
- Singleton s1 = Singleton.INSTANCE;
- Singleton s2 = Singleton.INSTANCE;
- Singleton s3 = Singleton.INSTANCE;
- Singleton s4 = Singleton.INSTANCE;
- // error: cannot assign a value to final variable INSTANCE
- // 如果Single类的INSTANCE属性使用final进行,下一句代码将报语法错误!
- Singleton.INSTANCE = null;
- boolean result = s1 == s2;
- System.out.println("result="+result);
- boolean result2 = s3 == s4;
- System.out.println("result2="+result2);
- // Java中规定,不能对空对象进行操作.
- // NullPointerException
- Singleton s5 = Singleton.INSTANCE;
- s5.show();
- }
- }
- // 设计一个 `单例类`
- class Singleton
- {
- // 属性
- private Singleton () {}
- public static final Singleton INSTANCE = new Singleton ();
- public void show()
- {
- System.out.println("show...");
- }
- }
- 懒汉式和饿汉式单例
饿汉式单例 :
特点: 不管你单例对象什么时候用,类一加载,我就直接在堆区中先来创建这个单例对象.
- class Demo
- {
- public static void main(String[] args)
- {
- Singleton s1 = Singleton.getInstance();
- Singleton s2 = Singleton.getInstance();
- System.out.println(s1 == s2);
- }
- }
- class Singleton
- {
- // 1. 创建一个本类的对象
- private static Singleton INSTANCE = new Singleton (); // 静态成员变量,跟随类的加载而加载. 该对象在类加载的时候就被创建完成了.
- // 2. 私有化构造方法
- private Singleton () {}
- // 3. 提供一个共有方法来返回该类的对象
- public static Singleton getInstance()
- {
- return INSTANCE;
- }
- }
懒汉式单例 :
特点: 在类加载的时候,不会在堆区中创建单例对象.
- class Demo
- {
- public static void main(String[] args)
- {
- Singleton s1 = Singleton.getInstance();
- Singleton s2 = Singleton.getInstance();
- System.out.println(s1 == s2);
- }
- }
- class Singleton
- {
- // 1. 创建一个本类的对象
- private static Singleton INSTANCE = null; // 类加载的时候不创建对象.
- // 2. 私有化构造方法
- private Singleton () {}
- // 3. 提供一个共有方法来返回该类的对象
- public static Singleton getInstance()
- {
- if (INSTANCE == null)
- {
- INSTANCE = new Singleton ();
- }
- return INSTANCE;
- }
- }
特点 : 单例对象什么时候用,我就什么时候来创建.
假设main方法有1000行代码,如果在第800行代码(getInstance())用到了单例,此时前800行代码运行时,不会在堆区中创建单例对象,但是当运行到第800行代码时,才会开始在堆区中来创建单例对象.