设计模式之-单例模式

java设计模式之单例模式——Singleton pattern 设计模式故事会:https://blog.youkuaiyun.com/weixin_40205234/article/details/90664824 单例模式 单例模式(Singleton pattern)是java中最常见的设计模式之一。该模式属于创建型设计模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一... 阅读详情

一、写这些原因是因为学习时候,我们只有知识的输入但是没有知识的转化和输出。所以想通过博客的形式来将学到知识 自己通过自己的语言和理解将其表述出来那么知识才能记得牢固才能 更能加深自己的理解。
1、单例模式(Singleton): 是一种常用的设计模式,在java应用中,单例对象能保证在一个jvm中,该对象的实例只有一个。
那么使用单例模式有什么好处呢?
a.某些类创建比较频繁,对于一些大型的对象创建时 比较消耗系统的资源。
b. 不需要new操作符去创建实例,减少了系统内存的使用频率,减轻GC压力。
c. 在整个系统中使用全局变量共享资源。
2、单例模式有分为 饿汉式,懒汉式,以及多线程版本。
一般简单不考虑多线程的话就是饿汉式,懒汉式创建。饿汉式就是立即创建一个对象而不是在需要的时候再创建。懒汉式就是在需要创建对象实例的时候才去创建。
3、首先使用 饿汉式来创建单例。

package com.springmvc.headfrist.singleton;
//最简单单例
/**
 * <br/>
 * @return
 * @exception   
 * @author lin
 * @Date  2017/5/3
 **/
public class Singleton {
	 /**
	 持有私有静态实例,防止被引用
	  如果不设计为private ,而是public那么 我们在外边就可以通过类名来调用,并且可以将其设置为null.
	  */  
    private static Singleton instance = new Singleton();  
   
    // 也可以使用静态块的方式创建
	// static {
	//        instance = new Singleton();
	//    }
   
  
    /**
     *  私有构造方法,防止被实例化,如果在类里面有私有构造器,则下面
     * 例如:Singleton singl=new Singleton();(为错误的)
     */  
    private Singleton() {  
    }  
    
    /**
     *  创建静态方法,那么在外部调用时就可以通过类名.getInstance() 获取实例。
     */  
  public static Singleton getInstance() {  
      // 如果返回 return new Singleton(); 这样是不对的,因为这样每次调用都会产生一个新的实例。这和我们的单例模式 只有
      // 实例相违背。
        return instance;  
    }  
}
/**
 测试调用
*/
public class Demo {
    public static void main(String[] args) {
        //
        SingletonTest instance = SingletonTest.getInstance();
        int count =100;
        for (int i = 0; i < count; i++) {
            SingletonTest singletonTest = SingletonTest.getInstance();
            // 比较地址,如果不相等那么就会执行下面的打印
            if( instance != singletonTest){
                System.out.println("一个新的对象被创建了"+ instance);
            }
        }
        System.out.println("程序结束了");
    }
}

运行结果是: 程序结束了
在这里插入图片描述
这就是说明了创建的 对象实例时同一个对象实例。
对于饿汉式模式的单例 有一个问题就是 Singleton对象暂时不需要使用 但是在类进行加载已经实例化好了这样就造成了一定程度上的性能损耗,所以 我们采用懒汉式的方式来创建单例模式。

4、懒汉式的方法来创建 就是在需要使用到实例对象是才去创建。

package com.springmvc.headfrist.singleton;
/**
 * <br/>
 * @author lin
 * @Date  2017/5/3
 **/
public class Singleton2 {
	
    private static Singleton2 instance;  

    private Singleton2 () { 
      System.out.println("---------------新的SingletonTest2对象被创建了--------------"); 
    }  
 
  public static Singleton2 getInstance() {  
        if(instance == null){
            instance = new Singleton2 ();  
        }
        return instance ;
    }  
}
/**
  测试
 * @ClassName: Demo2
 * @Description:
 * @Author: lin
 * @Date: 2017/5/3 
 * History:
 * @<version> 1.0
 */
public class Demo2 {
    public static void main(String[] args) {
        int count =100;
        for (int i = 0; i < count; i++) {
            SingletonTest2.getInstance();
        }
    }
}

程序运行结果是: ---------------新的SingletonTest2对象被创建了--------------
在这里插入图片描述
从结果我们可以看到只是创建了一个实例对象。

这种创建就是懒汉式。和饿汉式的区别就是在声明instance没有直接去实例化,并且对instance进行一个null的判断。

不过对于上述的两种创建方式在多线程情况下就会出现问题。出现什么问题呢?我们使用懒汉式来测试一下

public class Demo2 {
    public static void main(String[] args) {
        int count =100;
        ExecutorService executorService = new ThreadPoolExecutor(5,20,200,
                TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(5),
                new DefaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

        for (int i = 0; i < count; i++) {
            executorService.execute(new MyThread());
        }
    }
}

class MyThread implements Runnable {

    @Override
    public void run() {
        SingletonTest2.getInstance();
    }
}

执行结果,可以看到在多线程下 会产生多个对象。所以在多线程下面这种方法不是单例模式。我们需要怎么去修改呢?让其在多线程下也只创建一个对象实例。一般我们想到的就是添加锁的方法来确保对象实例的创建。
在这里插入图片描述
5、我们可以通过 添加synchronized锁来实现多线程条件下的控制。

/**
 * @ClassName: SingletonTest3
 * @Description:
 * @Author: lin
 * @Date: 2017/5/3
 * History:
 * @<version> 1.0
 */
public class SingletonTest3 {
    private static  SingletonTest3 instance = null;

    private SingletonTest3(){
        System.out.println("---------------新的SingletonTest3对象被创建了--------------");
    }

    public static  SingletonTest3 getInstance(){
        if(instance == null){ 
            synchronized (SingletonTest.class){
                if(instance == null){
                    instance = new SingletonTest3();
                }
            }
        }
        return  instance;
    }
}
package com.springmvc.headfrist.singlet;

import com.springmvc.headfrist.DefaultThreadFactory;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
测试
 * @ClassName: Demo3
 * @Description:
 * @Author: lin
 * @Date: 2017/5/5 
 * History:
 * @<version> 1.0
 */
public class Demo3 {

    public static void main(String[] args) {
        int count =100;
        ExecutorService executorService = new ThreadPoolExecutor(5,20,200,
                TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(100),
                new DefaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        for (int i = 0; i < count; i++) {
            executorService.execute(new MyThread1());

        }
    }
}

class MyThread1 implements Runnable {

    @Override
    public void run() {
        SingletonTest3.getInstance();
    }
}

执行结果我们可以看到这种方式下 创建的实例对象只有一个,这样在多线程的情况下只生成一个实例对象
在这里插入图片描述
但是这种 双重检查模式 (目前被称为反模式,不提倡使用这种方式),进行了两次的判断,第一次是为了避免不要的实例,第二次是为了进行同步,避免多线程问题。 synchronized 关键字修饰的代码块被称为同步块,synchronized关键字所引导的代码块就是临界区(锁的持有线程在其获取锁之后和释放之前这段时间所执行的代码被称为临界区 ),临界区内的代码会进行重排序 由于 instance = new SingletonTest3(); 对象的创建在JVM中可能会进行重排序,并且临界区外的代码 可以被重排序到临界区,但是临界区内的语句不能被重排序到临界区外,所以这种在多线程情况下存在风险。 不过我们可以使用volatile修饰instance 实例变量有效,解决该问题。

6、我们可以使用静态类内部类的方式来实现单例模式

package com.springmvc.headfrist.singlet;

/**
 * 静态类部类
 * @ClassName: SingletonTest4
 * @Description:
 * @Author: lin
 * @Date: 2017/5/3
 * History:
 * @<version> 1.0
 */
public class SingletonTest4 {

    private SingletonTest4(){
        System.out.println("---------------新的SingletonTest4对象被创建了--------------");
    }

    private static  class SingletonFactory{
        final static  SingletonTest4 instance = new SingletonTest4();
    }

    public static SingletonTest4 getInstance(){
        return  SingletonFactory.instance;
    }

    public void test(){
        System.out.println("static class SingletonFactory ....");
    }
}

package com.springmvc.headfrist.singlet;

import com.springmvc.headfrist.DefaultThreadFactory;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
测试
 * @ClassName: Demo4
 * @Description:
 * @Author: lin
 * @Date: 2017/5/3
 * History:
 * @<version> 1.0
 */
public class Demo4 {
    public static void main(String[] args) {
        int count =100;
        ExecutorService executorService = new ThreadPoolExecutor(5,20,200,
                TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(100),
                new DefaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

        for (int i = 0; i < count; i++) {
            executorService.execute(new MyThread2());

        }
    }
}

class MyThread2 implements Runnable {

    @Override
    public void run() {
        SingletonTest4.getInstance();
    }
}

执行结果
在这里插入图片描述
从执行的结果来看 产生的实例对象只有一个,一般来说创建单例的模式有很多种没有十分完美方案。我们只能根据实际情况,选择选择适合自己应用场景的方法。

7、注意序列化对单例的破坏

package com.springmvc.headfrist.singleton;

import java.io.Serializable;

/**
 * 使用双重校验锁方式实现单例
 * 测试 序列化对一个单例的破坏
 * <p>Title:SingletonSerializable</p>
 * @author liuwanlin
 * @date 2017年5月4日上午11:45:02
 */
public class SingletonSerializable implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 8607398639911248517L;
	
	
	private volatile static SingletonSerializable singletonSerializable;
	
	private SingletonSerializable(){
		System.out.println("---------------新的SingletonSerializable对象被创建了--------------");
	}

	public static SingletonSerializable getSingletonSerializable(){
		if(singletonSerializable==null){
			synchronized (SingletonSerializable.class) {
				if(singletonSerializable == null){
					singletonSerializable = new SingletonSerializable();
				}
			}
		}
		return singletonSerializable;
	}
	
//	private Object readResolve() {
//		return singletonSerializable;
//	}
}

public class Demo4Serializable {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 输出流   字节
        ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream("tempFile"));
        // 调用writeObject的方法将字节写到流中
        obj.writeObject(SingletonSerializable.getSingletonSerializable());
        File file = new File("tempFile");
        // 输入流
        ObjectInputStream outputStream= new ObjectInputStream(new FileInputStream(file));
        SingletonSerializable newInstance = (SingletonSerializable ) outputStream.readObject();

        System.out.println( newInstance ==   SingletonSerializable.getSingletonSerializable());
        obj.flush();
        obj.close();
        outputStream.close();
    }
}

测试结果如下
在这里插入图片描述

从结果可以知道 序列化之后两个实例对象不相等,这不符合单例模式的定义。那么是哪里出了问题呢?

我们进行debug进一步分析 ,下面读取流地方 我们去看看到底做了些什么
在这里插入图片描述
进入ObjectInputStream类中 readObject()方法。首先会去判断enableOverride是否为true, 如果为true就执行readObjectOverride(), 如果没有那么就往下执行。这为false所以继续往下执行。执行到readObject0()方法的时候这里面做了什么处理呢?
在这里插入图片描述
进入到readObject0方法

  /**
     * Underlying readObject implementation.
     */
    private Object readObject0(boolean unshared) throws IOException {
        boolean oldMode = bin.getBlockDataMode();
        if (oldMode) {
            int remain = bin.currentBlockRemaining();
            if (remain > 0) {
                throw new OptionalDataException(remain);
            } else if (defaultDataEnd) {
                /*
                 * Fix for 4360508: stream is currently at the end of a field
                 * value block written via default serialization; since there
                 * is no terminating TC_ENDBLOCKDATA tag, simulate
                 * end-of-custom-data behavior explicitly.
                 */
                throw new OptionalDataException(true);
            }
            bin.setBlockDataMode(false);
        }

        byte tc;
        while ((tc = bin.peekByte()) == TC_RESET) {
            bin.readByte();
            handleReset();
        }

        depth++;
        totalObjectRefs++;
        try {
            switch (tc) {
                case TC_NULL:
                    return readNull();

                case TC_REFERENCE:
                    return readHandle(unshared);

                case TC_CLASS:
                    return readClass(unshared);

                case TC_CLASSDESC:
                case TC_PROXYCLASSDESC:
                    return readClassDesc(unshared);

                case TC_STRING:
                case TC_LONGSTRING:
                    return checkResolve(readString(unshared));

                case TC_ARRAY:
                    return checkResolve(readArray(unshared));

                case TC_ENUM:
                    return checkResolve(readEnum(unshared));

                case TC_OBJECT:
                    return checkResolve(readOrdinaryObject(unshared));

                case TC_EXCEPTION:
                    IOException ex = readFatalException();
                    throw new WriteAbortedException("writing aborted", ex);

                case TC_BLOCKDATA:
                case TC_BLOCKDATALONG:
                    if (oldMode) {
                        bin.setBlockDataMode(true);
                        bin.peek();             // force header read
                        throw new OptionalDataException(
                            bin.currentBlockRemaining());
                    } else {
                        throw new StreamCorruptedException(
                            "unexpected block data");
                    }

                case TC_ENDBLOCKDATA:
                    if (oldMode) {
                        throw new OptionalDataException(true);
                    } else {
                        throw new StreamCorruptedException(
                            "unexpected end of block data");
                    }

                default:
                    throw new StreamCorruptedException(
                        String.format("invalid type code: %02X", tc));
            }
        } finally {
            depth--;
            bin.setBlockDataMode(oldMode);
        }
    }

在这个方法中实际上调用的是 readOrdinaryObject(unshared);方法
在这里插入图片描述

在该方法中有个三目运算 obj = desc.isInstantiable()? desc.newInstance(): null;
而isInstantiable()方法的 表示 如果一个serializable/externalizable的类可以在运行时被实例化,那么该方法就返回true. 对于desc.newInstance() 则表示 该方法通过反射的方式调用无参构造方法新建一个对象。
这里使用序列化的方式所以 desc.isInstantiable() 为true 那么 将使用 反射的方式去创建一个新的对象。所以从这里我们就可以知道 为什么序列化可以破坏单例了。
在这里插入图片描述
那么我们该如果去防止序列化对单例的破坏呢?我们可以在SingletonSerializable定义一个readResolve方法。我们将上面SingletonSerializable类中 readResolve方法注释取消再进行测试。

public class SingletonSerializable implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 8607398639911248517L;
	
	
	private volatile static SingletonSerializable singletonSerializable;
	
	private SingletonSerializable(){
		System.out.println("---------------新的SingletonSerializable对象被创建了--------------");
	}

	public static SingletonSerializable getSingletonSerializable(){
		if(singletonSerializable==null){
			synchronized (SingletonSerializable.class) {
				if(singletonSerializable == null){
					singletonSerializable = new SingletonSerializable();
				}
			}
		}
		return singletonSerializable;
	}
	
	private Object readResolve() {
		return singletonSerializable;
	}
}

public class Demo4Serializable {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 输出流   字节
        ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream("tempFile"));
        // 调用writeObject的方法将字节写到流中
        obj.writeObject(SingletonSerializable.getSingletonSerializable());
        File file = new File("tempFile");
        // 输入流
        ObjectInputStream outputStream= new ObjectInputStream(new FileInputStream(file));
        SingletonSerializable newInstance = (SingletonSerializable ) outputStream.readObject();

        System.out.println( newInstance ==   SingletonSerializable.getSingletonSerializable());
        obj.flush();
        obj.close();
        outputStream.close();
    }
}

测试结果
在这里插入图片描述
从测试结果来看 两个对象实例相同,说明是同一个对象。那么为什么添加了readResolve方法 就能避免序列化对象单例模式的破坏呢?在readOrdinaryObject 方法中 一个判断是调用 desc.hasReadResolveMethod()方法 。 hasReadResolveMethod方法是 如果一个类 实现了serializable 或者 externalizable接口的类中包含readResolve则返回true。 那么它将会去调用 invokeReadResolve方法 ,通过反射的方式调用要被反序列化的类的readResolve方法。
所以,原理也就清楚了,主要在SingletonSerializable 中定义readResolve方法,并在该方法中指定要返回的对象的生成策略,就可以防止单例被破坏。
在这里插入图片描述
hasReadResolveMethod方法。
在这里插入图片描述
invokeReadResolve 方法
在这里插入图片描述

新手避坑指南:用SARScape 5.6.2处理Sentinel-1数据做SBAS-InSAR,这些参数设置错了白忙活 本文详细介绍了使用SARScape 5.6.2处理Sentinel-1数据做SBAS-InSAR时的关键参数设置技巧,帮助新手避免常见错误。重点解析了连接图生成、干涉工作流、DEM处理等环节的12个关键参数,包括Max Normal Baseline、Unwrapping Coherence Threshold等,提供实测安全值范围和优化建议,确保处理效率和结果准确性。 阅读详情

相关推荐

硬全桥副边钳位管Vds电压凸台揭秘——寄生参数引发的导通异常

本文深入分析了硬全桥副边钳位管Vds电压凸台现象,揭示了寄生参数如何引发导通异常。通过波形分析和工程实践,详细解析了走线电感的蓄能效应和体二极管的接力作用,并提供了PCB布局优化、元件选型和驱动电路调整等解决方案,帮助工程师有效应对这一常见问题。

weixin_30825581的博客 429

java readobject源码解读和反序列化分析

首先看java.io.readobject函数: public final Object readObject() throws IOException, ClassNotFoundException { if (enableOverride) { return readObjectOverride(); } // if nested read, passHandle contains handle of en

一个码农的笔记 4万+

用python自动复制粘贴excel表里某一列的数据到另一个表中

昨天接到人事小姐姐求助减轻复制粘贴的重复工作量,分享一下代码 半路新手上路 耶 把 2.xlsx 表里的第二列 的数据复制粘贴到 test.xlsx的第一列 python3.6.2 from openpyxl import Workbook from openpyxl import load_workbook from openpyxl.writer.excel import Exc...

weixin_33854644的博客 2万+

序列化与反序列化

Java序列化是把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程。在网络传输过程中,需要以字节流的形式来传输数据;而字节的可以还原成完全相等的对象,这个相反的过程又称为反序列化;

m566666的博客 1475

MATLAB2022a安装避坑指南:从下载到破解的完整流程(附常见错误解决方案)

本文提供MATLAB2022a在Windows系统下的完整安装教程与深度配置指南。内容涵盖从系统兼容性检查、安装媒介验证到分步安装、自定义产品选择及安装后优化设置的全流程。重点解析了安装过程中常见的权限、空间、许可证错误,并提供了系统性的故障诊断与解决方案,旨在帮助用户构建稳定高效的科研计算环境。

weixin_29057695的博客 439

机器视觉--线扫相机触发:从原理到选型,构建高效成像方案

本文深入解析线扫相机触发技术,从硬件编码器触发到软件触发方案,提供详细的性能对比和选型指南。通过实际案例展示如何构建高效成像方案,特别适合机器视觉领域需要精准控制的应用场景,如工业检测和自动化生产线。

weixin_42531886的博客 415

【详解java序列化&反序列化】

一、什么是序列化和反序列化 把对象转换为字节序列的过程称为对象的序列化;把字节序列恢复为对象的过程称为对象的反序列化。 序列化类必须实现Serializable或Externalizable接口 对象的序列化主要有两种用途:          1、把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;         2、在网络上传送对象的字节序列。 二、什么是serialVersionUID

lyc87007643的博客 912

C语言试题四之计算并输出3到n之间所有素数的平方根之和

1、题目 请编写函数function,它的功能是:计算并输出3到n之间所有素数的平方根之和 例子:若我们main函数从键盘给n输入5之后,我们需要输出结果为3.968119 输入值n的要求:正整数n, 要求小于100。 2、部分函数说明 C 库函数 double sqrt(double x) 返回 x 的平方根 3、源代码实现 #include <stdio.h> #...

码莎拉蒂 7232

Java序列化与反序列化详解后续

Java Socket编程实例:[url]http://donald-draper.iteye.com/blog/2356695[/url] java Socket读写缓存区Writer和Reader:[url]http://donald-draper.iteye.com/blog/2356885[/url] Java NIO ByteBuffer详解:[url]http://donald-d...

Donald_Draper 931

Access查询中的Dlookup函数的妙用

在Microsoft Access中,处理和分析数据的过程中,常常会遇到需要根据条件从其他记录中提取特定数据的情况。这时候,Dlookup函数就成了开发者和数据分析师的得力助手。今天我们将通过一个具体的实例,详细探讨如何利用Dlookup函数来解决复杂的查询问题。

m0_62153576的博客 294

Android Input——输入系统介绍(一)

Input 系统对于提供流畅、灵敏和一致的用户交互体验至关重要,它需要在不同的设备、场景和应用中保证输入事件的正确性、及时性和安全性。Android 输入系统是一个复杂但高效的设计,旨在处理来自各种输入设备(如触摸屏、键盘等)的用户交互,并将这些交互转换为应用程序可以理解和响应的形式。EventHub:输入系统的最底层,直接与硬件通信,监听和读取输入设备的原始事件。:从 EventHub 获取原始输入事件,对其进行解析,转化为更高层次的事件,以便上层应用或服务能够理解。

小旭的专栏 1712

单例模式安全之序列化攻击

源码 什么是序列化攻击呢? 简单说,一个单例对象经过序列化再反序列化后,内存中会存在两个对象,这样单例模式就被破坏。 序列化攻击复现 序列化攻击复过程 获取到单例对象 对象序列化持久到磁盘 反序列化成对象 这里采用JDK的自带的序列化方式 单例实现Serializable接口 package com.fine.serialize; import java.io.Serializable;...

qq_29879799的博客 564

从零开始创建Davinci Configurator配置工程

本文介绍了从零开始搭建达芬奇工程的详细步骤。首先安装Vector的CBD包后,通过DavicCFG.exe新建空白ECU工程。文章提到Postbuild相关概念可参考往期文章《AUTOSAR配置中的PostBuild、Precompile、Linktime》,并预告下期将讲解如何通过导入DBC文件来启用AUTOSAR模块。全文以实操截图为主,步骤清晰简明,适合开发者参考备份。

Xiaowestwind的博客 218

设计模式-单例模式(Singleton Pattern)

单例模式 定义 确保一个类只有一个实例,并为整个系统提供一个全局访问点 (向整个系统提供这个实例)。 类型 创建型。 适用场景 网站访问量计数器。 项目中用于读取配置文件的类。 Spring中,每个Bean默认都是单例的,这样便于Spring容器进行管理。 优点 由于单例模式只生成了一个实例,所以能够节约系统资源、减少性能开销、提高系统效率。 缺点 不适合用于变化频繁的对象;如果实例化的对象长...

kaven 5158

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

23种设计模式中的单例模式(Singleton Pattern)

本篇文章将23种设计模式中的单例设计模式,此篇文章为一天学习一个设计模式系列文章,后面会分享其他模式知识。

小威的博客 2万+

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

设计模式之单例模式(Singleton Pattern)

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。主要解决:一个全局使用的类频繁地创建与销毁。何时使用:当您想控制实例数目,节省系统资源的时候。如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。关键代码:构造函数是私有的。

weixin_42294716的博客 1398

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

23种设计模式之单例模式(Singleton Pattern)【设计模式】

📒单例模式(Singleton Pattern)是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式主要用于控制资源的访问,确保某些类只有一个实例,并且这个实例能够被全局访问。

李赛赛的专栏 1101

设计模式:单例模式(Singleton Pattern)

单例模式(Singleton Pattern)是一种创建型设计模式,它的核心思想是:保证在一个进程中,某个类仅有一个实例,并提供全局访问点。

TechNomad的博客 1456

设计模式——单例模式(Singleton Pattern)

设计模式——单例模式(Singleton Pattern) 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在有些场景中,为了节省内存资源、保证数据内容的一致性,对某些类要求只能创建一个实例,且该类能自行创建这个实例,这就是所谓的单例模式 文章目录设计模式——单例模式(Singleton Pattern)单例模式的优缺点优点缺点单例模式的应用场景单例模式与静态类的区别常见的7种实现方式1.饿汉模式2.懒

qq_42498542的博客 833

实践GoF设计模式:Singleton Pattern 单例模式

前言 我们在开发项目中,经常会遇到这种情况,为了节约所拥有的系统资源或数据的一致性时,需要保证系统中的某个类中有且只有唯一的一个实例,而且在其创建成功之后,我们将不能再次创建同类型的其他对象,也就是所有的操作都要以这个唯一的实例为中心,所以为了保证对象所具有的的唯一性,单例模式成为我们所具备的方法 概念 ● 设计模式中单例模式是最为简单的形式之一,而且是使用最广泛的设计模式之一,其目的是为了将类的一个对象成为系统中的唯一实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享 ● 要想实现这一点,可以

m0_70748458的博客 402

设计模式总结之Singleton Pattern(单例模式)

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

cooldragon的专栏 4858

设计模式之单例模式

本文主要介绍了设计模式的相关内容,包括设计模式的概念、常见设计模式及 GoF 设计模式的分类。重点阐述了单例模式,从其核心思想、实现方式展开,如通过对比非单例的 `Student` 类实例化结果,引出单例模式。详细介绍了饿汉式、懒汉式(线程不安全)、线程安全的懒汉式、双重检查锁、静态内部类和枚举等多种单例模式的实现方式,以代码示例及测试展示特点,分析了各实现方式的优缺点,如直接在方法上加锁的线程安全懒汉式会因频繁加锁致并发性能差,以及对性能的优化目标,还提及单例模式的应用场景及优缺点,并在最后对单例模式进行

m0_73941339的博客 1767

golang mysql单例模式_GoLang 设计模式之单例模式 (Singleton Pattern)

软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设 计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。???? 单例模式 (Singleton Pattern)现实世界的例子:一次只能有一个国家的总统。简单来说:确保只创建特定类的一个对象。单例模式实际上被认为是反模式,应该避免过度使用它。它不...

weixin_39924573的博客 281

设计模式——单例模式(Singleton Pattern)+ Spring相关源码

确保一个类只有一个实例,并提供了一个全局访问点来访问该实例。避免一个全局使用的类频繁地创建与销毁。

码鹿的记录 367
上一篇: 谈谈对springioc的理解
下一篇: 设计模式之-工厂模式和抽象工厂模式
lin59106
博客等级 码龄14年 5粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值