持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情
前言
之前经常听说一些设计模式,比如工厂模式,代理模式,单例模式等,但是一直都是听说,没有太多了解。直到突然遇到了。。。。
概念
设计模式:通过百度我们可以看到这样的解释
提取关键点,反复使用,经验总结。
说人话就是套路,模板
单例设计模式:
里面的核心就是:只new一次对象实例。
这么才能只new一次? 当然是:🤔构造器私有化,这样其他类就不能访问构造器,不能进行new操作了。 但是👀:在咱类内部,还是可以访问,然后其他类只能访问调用该类的某静态方法来返回创建当前类对象,静态方法只能访问静态变量。所以俺们把类内部产生的对象的变量,定义成静态的。
👌👍要实现单例设计模式,创建的类需要满足以下 3 个条件:
- 构造方法私有。
- 用一个私有的,静态引用类型实例变量。
- 提供一个公有的,静态方法来获得该实例。
单例模式1------懒汉式
🤔 那什么叫懒汉式呢?
懒汉式就是延迟加载,所谓延迟加载就是调用提供公共的静态的方法时实例才被创建出来。
比如创建一个独立的类xx,声明一个私有静态变量 s,提供一个私有构造方法,提供一个公共的静态返回对象方法。方法里面,如果s为null,就new一个对象赋给s,如果s存在,就直接返回 实现代码如下:👇
class Singleton1{
// 私有的静态的引用类型变量
private static Singleton1 s;
// 私有的构造器
private Singleton1(){
}
// 公共的静态的可返回该类的实例
public static Singleton1 getInstance(){
if(s == null){
s = new Singleton1();
}
return s;
}
}
我们可以设计一个test类
Singleton1 s1 = Singleton1.getInstance();
System.out.println(s1);
Singleton1 s2 = Singleton1.getInstance();
System.out.println(s2);
System.out.println(s1 == s2);
然后看看结果。(从结果中看到,两个对象打印的地址完全相同。)
单例模式2------饿汉式
🤔 那什么叫饿汉式呢?
饿汉式就是立即加载,所谓立即加载就是使用该类的时候先将对象创建,不管以后会不会使用到该对象。
创建一个独立类xx2,声明一个私有静态最终的常量 s,初始化new一次。(因为这里已经new了,所以final修饰,不让修改之类的)提供一个私有的,无参构造方法。外部不能通过 new 创建对象;提供一个公共的静态的返回对象方法。
实现代码如下:👇
class Singleton2{
// 私有的静态的最终的的引用类型的对象
private static final Singleton2 S = new Singleton2();
// 私有构造器
private Singleton2(){
}
// 公共的静态的可返回该类的实例
public static Singleton2 getInstance(){
return S;
}
}
同理,可以使用上面test方法来测试。
为啥要分两种,有啥区别?
立即加载(饿汉):如果加载的东西很大怎么办?一次全部加载了,暂时不使用是不是浪费内存? 延迟加载(懒汉):使用才加载。按需加载
但是真正使用一般是双重检查和枚举。
为啥不用懒汉饿汉?
假设s1是张三调用 Singleton1 s1 = Singleton1.getInstance(); s2是李四调用 Singleton1 s2 = Singleton1.getInstance(); 并且他们两个几乎同时执行代码(多线程)
问题出现了:假设张三刚刚执行到懒汉式的 if(s==null)没有new 这个时候李四进入if判断,这个时候两个都是null(线程不安全),那么会new两次 所以懒汉饿汉是在非高并发情况使用
改进
延迟加载:(双重检查————懒汉进阶)
class Singleton1{
// 私有的静态的引用类型变量
private static Singleton1 s;
// 私有的构造器
private Singleton1(){
}
// 公共的静态的可返回该类的实例
public static Singleton1 getInstance(){
if(s == null){
//假设张三李四同时进入(需要加锁进行互斥操作————这里需要使用操作系统里面信号量机制实现。)
synchronized(任意对象){
//排队(比如先zs再李四)
if(s==null){
s = new Singleton1();
}
}
}
return s;
}
}
🤔🤔🤔第一个if能不能不加????
语法上可以不加,但是逻辑上和经验上建议不省略。
🤔🤔🤔第一个if干嘛的????
避免等待,提高效率(假设非常多线程进来,第一个new了,后面非常多的进来,没有第一个if他们也会加锁排队,等待判断,但是实际上,他们完全不用等待,他们可以直接return的)
立即加载(枚举)
public enum Singleton{INSTANCE;}
就一句话,枚举天生单例,缺点不能延迟加载
Singleton1 s1 = Singleton1.INSTANCE;
Singleton1 s2 = Singleton1.INSTANCE;
最后,这个模式不是只能Java使用,所有语言都能的,我看百度大部分是java解答
好的,大家快去试试吧!