1.引子
说起设计模式,做过开发的你一定不会感到陌生,甚至随口都能说上几个。比如单例设计模式、工厂设计模式、建造者设计模式、模板设计模式、策略设计模式、装饰者设计模式、责任链设计模式、观察者设计模式、代理设计模式、适配器设计模式。
你看我一口气就列举了10种常见的设计模式,寓意为十全十美,事实上在gof设计模式中,一共有23种设计模式,细分类为创建型、结构型、行为型设计模式。每一种设计模式都是无数前辈们经验智慧的结晶,都为了解决某一问题域而诞生,实实在在。
今天开始,我想推荐你一起来学习设计模式,不管我们是前端开发工程师,还是后端开发工程师,我觉得都有必要。一来通过学习理解设计模式,有助于提升我们的设计编码内功;二来通过学习理解设计模式,有助于我们在寻找工作机会的时候,与面试官用愉快的心情聊天,不至于尬聊;三嘛当然则是设计模式是我们通往高级工程师,架构师的必备基本技能之一。
那么让我们一起开始吧,今天我们先来聊一聊单例设计模式。
2.案例
2.1.什么是单例设计模式
单例设计模式,重点两个字是单例。我们用更直观的描述则是说,一个类,在整个应用系统中,有且仅有一个实例对象。
有关单例设计模式的应用场景,我们试想这样一个需求:全局唯一。每个应用系统都有配置文件,通过配置文件统一配置整个应用环境信息,比如数据库连接信息、缓存redis连接信息等。
在系统启动加载的时候,需要将配置文件内容读取解析存储到内存。从整个应用的角度,配置信息独一无二,我们只需要存储一份就够了。这样带来的好处有,一来方便数据一致性的维护,如果需要修改更新配置信息,只需要维护一份;而来只存储一份,即节省了内存资源开销,省资源。
你看这就是单例设计模式的应用场景,以及它所带来的收益,很好理解对吧。理解了单例设计模式,我们再来看一下如何通过代码实现,talk is cheap, show me you code!
关於单例设计模式,有两种实现方式:饿汉式、以及懒汉式。我们都一起来看一下如何实现。都比较简单,我就直接上代码了,代码中我配备了相关注释,相信你一看就都能明白。
2.2.饿汉式实现单例设计模式
/**
* 单例设计模式:
* 1.一个类,在整个系统中有且仅有一个对象,称为单例设计模式
* 2.比如:配置文件信息,在整个系统中只需要一份配置文件,便于实现信息一致性维护,
* 同时节省内存资源
* 3.单例设计模式实现方式:饿汉式,懒汉式
*
* @author ThinkPad
* @version 1.0
* @date 2021/2/21 16:26
*/
public class HungrySingleton {
public static void main(String[] args) {
System.out.println("饿汉式实现IdGenerator 生成器:"
+ IdGenerator.getInstance().getId());
}
/**
* 单例设计模式,饿汉式实现Id生成器
*/
static class IdGenerator{
private AtomicInteger id = new AtomicInteger(0);
/**
* 饿汉式,创建对象线程安全
*/
private static IdGenerator instance = new IdGenerator();
/**
* 构造方法私有化
*/
private IdGenerator(){}
/**
* 提供公有的静态方法,获取实例
* @return
*/
public static IdGenerator getInstance(){
return instance;
}
public int getId(){
return id.incrementAndGet();
}
}
}
2.3.懒汉式实现单例设计模式
/**
* 单例设计模式:
* 1.一个类,在整个系统中有且仅有一个对象,称为单例设计模式
* 2.比如:配置文件信息,在整个系统中只需要一份配置文件,便于实现信息一致性维护,
* 同时节省内存资源
* 3.单例设计模式实现方式:饿汉式,懒汉式
*
* @author ThinkPad
* @version 1.0
* @date 2021/2/21 16:43
*/
public class LazySingleton {
public static void main(String[] args) {
System.out.println("懒汉式实现IdGenerator 生成器:"
+ IdGenerator.getInstance().getId());
}
/**
* 单例设计模式,懒汉式实现Id生成器
*/
static class IdGenerator{
private AtomicInteger id = new AtomicInteger(0);
/**
* 懒汉式,支持延迟加载,需要考虑创建对象时线程安全问题
* volatile关键字,保障内存可见性,及禁止指令重排序
*/
private static volatile IdGenerator instance;
/**
* 构造方法私有化
*/
private IdGenerator(){}
/**
* 提供公有的静态方法,获取实例,兼顾线程安全与性能
* 通过synchronized,与双重检测(double check)保障线程安全
* @return
*/
public static IdGenerator getInstance(){
if(instance == null){
synchronized (IdGenerator.class){
if(instance == null){
instance = new IdGenerator();
}
}
}
return instance;
}
public int getId(){
return id.incrementAndGet();
}
}
}