设计模式(一)--->单例模式(Singleton)
一:单例模式
1.简介
单例模式属于创建型模式,提供了创建对象的最佳方式
,这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建,并且该类提供了访问其唯一对象的方式
总的来说:
- 单例类只能有一个实例(static)
- 单例类只能自己创建自己的唯一实例(构造方法private修饰,参考enum类)
- 单例必须给其他对象提供自己访问的实例(通过自定义的public方法获取实例)
2.从需求目的的粗浅理解单例
- 意图: 保证一个类仅有一个实例,并提供它的全局访问点。
- 目的: 避免使用频繁的类频繁的创建和销毁 (spring默认创建bean是单例)
- 缺点: 没有接口,没有继承。
3.饿汉式实现单例模式
package com.htu;
public class Singleton {
//创建一个Singleton对象
private static Singleton instance = new Singleton();
//保证私有,这样该类就不可以被实例化
private Singleton(){
}
//有一个唯一可以访问对象的方法
public static Singleton getInstance(){
return instance;
}
public void doSomething() {
System.out.println("Do Something");
}
//调用
public static void main(String[] args) {
// 正确获取唯一单例方式
Singleton instance = Singleton.getInstance();
// 用单例做一些事情
instance.doSomething();
}
}
4.懒汉式实现单例模式(不安全)
- 线程不安全
- 延时加载(用到时再加在,避免浪费资源)
- 严格上不算单例
package com.htu;
public class LazySingleton {
//创建一个对象 延时初始化
private static LazySingleton lazySingleton;
//构造方法私有,保证自身初始化
private LazySingleton(){ }
//提供一个唯一的访问方法
public static LazySingleton getInstance(){
// 此处会有线程问题,如果线程A和线程B都执行到了步骤1,并未完成步骤2,那么就会创建多个实例
if(lazySingleton == null){
return new LazySingleton();
}
return lazySingleton;
}
public void doSomething(){
System.out.println("Do Something");
}
}
5.安全懒汉式实现单例模式
- 线程安全
- 懒加载
class SafeLazySingleTon{
//创建一个对象 演示初始化
private static SafeLazySingleTon safeLazySingleTon;
//构造方法私有 保证只会被自己实例化
private SafeLazySingleTon(){}
//提供一个唯一访问的这个实例的方法
public static synchronized SafeLazySingleTon getInstance(){
if(safeLazySingleTon == null){
return new SafeLazySingleTon();
}
return safeLazySingleTon;
}
public void doSomething(){
System.out.println("Do Something");
}
}
6.双检查锁实现安全懒汉式
上面getInstance 加锁,此时可以保证安全性,如果这个类访问次数较多会导致性能下降问题。我们实现双检查锁来缩小同步代码块的范围,用volatile来确保执行顺序不被打乱(指令重排序)
class TwoSafeLazySingTon{
//使用volatile关键字禁止指令重排
private static volatile TwoSafeLazySingTon twoSafeLazySingTon;
//构造方法私有,只能被自己实例化
private TwoSafeLazySingTon(){
}
//外部唯一可访问的对象
public static TwoSafeLazySingTon getInstance(){
//判断是不是单例的(步骤1)
if(twoSafeLazySingTon == null){
//锁住这个类,缩小范围(步骤2)
synchronized (TwoSafeLazySingTon.class){
//如果在锁住这个类的同时有线程执行到这里 我们需要判断执行完没有
if(twoSafeLazySingTon == null){
return new TwoSafeLazySingTon();
}
}
}
return twoSafeLazySingTon;
}
public void doSomething(){
System.out.println("Do Something");
}
}
7.静态内部类
上面我们发现它不是懒加载,是饿汉式加载。我们为了实现懒加载还有另外一种思路。调用静态内部类,用 classloader 机制来保证初始化 instance 时只有一个线程。
class StaticSingTon{
//设置一个静态内部类,调用这个内部类加载内容
private static class PrivateSingle{
//用final修饰 让其不可以改变
private static final StaticSingTon INSTACE = new StaticSingTon();
}
//私有构造方法,只有自己可以实例化
private StaticSingTon() {
}
//这里直接初始化这个静态内部类
public static StaticSingTon getInstance(){
//此时直接返回这个静态内部类的结果即可
return PrivateSingle.INSTACE;
}
}
本文来自博客园,作者:Diamond-fz,转载请注明原文链接:https://www.cnblogs.com/fzstudy/p/16206492.html
标签:
设计模式
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!