某些系统中为了节省内存资源、保证数据内容的一致性,对某些类要求只能创建一个实例,这就是所谓的单例模式。
单例模式属于创建型模式
,创建型模式
的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成。就像我们去商场购买商品时,不需要知道商品是怎么生产出来一样,因为它们由专门的厂商生产。
定义与特点
单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。
在计算机系统中,还有Windows的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、系统中的缓存等常常被设计成单例。
单例模式有 3 个特点:
- 单例类只有一个实例对象;
- 该单例对象必须由单例类自行创建;
- 单例类对外提供一个访问该单例的全局访问点;
结构
单例模式的主要角色如下:
- 单例类:包含一个实例且能自行创建这个实例的类。
- 访问类:使用单例的类。
实现
饿汉模式:
public class HungrySingleton {
private static final HungrySingleton instance = new HungrySingleton();
private HungrySingleton() {
}
public static HungrySingleton getInstance() {
return instance;
}
}
懒汉模式:
package com.lifengdi.designpatterns.demo.singleton;
/**
* 单例模式-懒汉模式
* 特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例
* 缺点是每次访问时都要同步,会影响性能,且消耗更多的资源
*
* @author 李锋镝
* @date Create at 11:24 2019/12/12
*/
public class LazySingleton {
//保证 instance 在所有线程中同步
private static volatile LazySingleton instance = null;
//private 避免类在外部被实例化
private LazySingleton() {
}
public static synchronized LazySingleton getInstance() {
//getInstance 方法前加同步
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
枚举:
package com.lifengdi.designpatterns.demo.singleton;
/**
* 单例模式-枚举
* 枚举也是一种特殊的单例模式。可以避免反射、序列化的问题。
*
* 反射问题:
* 懒汉模式和饿汉模式通过私有化构造方法来避免类在外部被实例化,
* 但是可以通过JAVA的反射机制调用私有构造方法来实例化单例类,所以私有化构造方法并不保险。
*
* 序列化问题:
* 懒汉模式和饿汉模式被序列化前后的对象并不相等(任何一个readObject方法,
* 不管是显式的还是默认的,它都会返回一个新建的实例,这个新建的实例不同于该类初始化时创建的实例)。
* 当然这个问题也可以被解决。
* @author 李锋镝
* @date Create at 11:36 2019/12/12
*/
public enum EnumSingleton {
INSTANCE;
public EnumSingleton getInstance(){
return INSTANCE;
}
}
除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接