设计模式篇之一文搞懂如何实现单例模式(一)

简介: 设计模式篇之一文搞懂如何实现单例模式(一)

单例模式


单例模式(SingletonPattern)是 Java 中最简单的设计模式之一。

单例模式一共存在 --> 懒汉式、饿汉式、懒汉+同步锁、双重校验锁、静态内部类、枚举这六种方式。

这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。

这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。


要求


  • 单例类只能有一个实例。
  • 单例类必须自己创建自己的唯一实例。
  • 单例类必须给所有其他对象提供这一实例。

为什么需要使用单例模式


  1. 只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。
  2. 解决一个全局使用的类频繁地创建与销毁问题。
  3. 其他场景自行脑部,单例即全局唯一对象,比如我们所熟悉的SpringBean默认就是单例的,全局唯一。

单例原理


单例的原理非常简单,我们让他唯一的方法就是让他不可用被new,那我们只需要私有化类的构造即可:


private ClassName() {
}


但是私有化后,我们不能new又如何创建对象呢?

我们首先要明白,private他是私有的,也就是不让外部其他类访问,那我们自己还是可以访问的,所以在上文的要求中就说到了:单例类必须自己创建自己的唯一实例。

同时我们还需要抛出单例的获取方法。


单例模式之懒汉式


创建单例类


public class SlackerStyle {
}


创建一个属性保存自身对象


public class SlackerStyle {
    private static SlackerStyle instance;
}


私有化构造


public class SlackerStyle {
    private static SlackerStyle instance;
    /**
     * 私有化构造方法(防止外部new新的对象)
     */
    private SlackerStyle() {
    }
}


自身创建对象与获取对象方法


public class SlackerStyle {
    private static SlackerStyle instance;
    /**
     * 私有化构造方法(防止外部new新的对象)
     */
    private SlackerStyle() {
    }
    /**
     * 提供一个静态的公有方法,当使用到该方法时,才去创建instance
     * 即懒汉式
     *
     * @return instance(单例对象)
     */
    public static SlackerStyle getInstance() {
        if (instance == null) {
            instance = new SlackerStyle();
        }
        return instance;
    }
}


当我们调用静态方法,它便会判断上面的静态属性instance中有无自身对象,无 --> 创建对象并赋值给instance,有 --> 返回instance


优缺分析


优点:延迟加载,效率较高。

缺点:线程不安全,可能会造成多个实例。

解释:延迟加载 --> 懒汉式只有在需要时才会创建单例对象,可以节约资源并提高程序的启动速度。


单例模式之懒汉式+锁


在以上的类中,对getInstance()方法添加synchronized锁,即可弥补线程不安全缺陷。


/**
     * 注意,此段为补充,为了解决线程不安全的问题,可以在方法上加上synchronized关键字,但是这样会导致效率下降
     * 提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
     * 此方法为线程安全的懒汉式,即懒汉+同步锁,就不额外写一个类了
     *
     * @return instance(单例对象)
     */
    public static synchronized SlackerStyle getInstance2() {
        if (instance == null) {
            instance = new SlackerStyle();
        }
        return instance;
    }


虽然弥补了线程不安全的缺陷,但是也失去了一部分效率,所以需要根据业务环境去选择适合的方法,鱼和熊掌不可兼得。


单例模式之饿汉式


还是如开始一样,创建好单例类,私有化构造方法。


public class HungryManStyle {
    /**
     * 私有化构造方法(防止外部new新的对象)
     */
    private HungryManStyle() {
    }
}


静态初始化对象

我们饿汉式是延迟加载的,即要用,然后第一次去调用时才会创建对象,而饿汉式恰恰相反,他在初始化类的时候就去创建。


静态初始化?

我们的static关键词修饰的方法或属性,在类加载之初遍开辟内存创建好了相关的内容了。

包括每个类的:


static{
}


中也一样的。

所以我们直接使用static修饰。


public class HungryManStyle {
    /**
     * 静态变量(单例对象),类加载时就初始化对象(不存在线程安全问题)
     */
    private static final HungryManStyle INSTANCE = new HungryManStyle();
    /**
     * 私有化构造方法(防止外部new新的对象)
     */
    private HungryManStyle() {
    }
    /**
     * 提供一个静态的公有方法,直接返回INSTANCE
     *
     * @return instance(单例对象)
     */
    public static HungryManStyle getInstance() {
        return INSTANCE;
    }
}


而且我们在类的静态属性创建时就new了一个自身对象了。

优缺分析

饿汉式的优点如下:

  1. 线程安全:由于在类加载时就创建单例对象,因此不存在多线程环境下的同步问题。
  2. 没有加锁的性能问题:饿汉式没有使用同步锁,因此不存在加锁带来的性能问题。
  3. 实现简单:饿汉式的实现比较简单,不需要考虑多线程环境下的同步问题。

饿汉式的缺点如下:

  1. 立即加载:由于在类加载时就创建单例对象,因此可能会影响程序的启动速度。
  2. 浪费资源:如果单例对象很大,并且程序中很少使用,那么饿汉式可能会浪费资源。

综上所述,饿汉式的优点是线程安全、没有加锁的性能问题和实现简单,缺点是可能影响程序的启动速度和浪费资源。

在选择单例模式的实现方式时,需要根据实际情况综合考虑各种因素,选择最适合的方式。

相关文章
|
29天前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
27 2
|
10天前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
18天前
|
设计模式 存储 数据库连接
PHP中的设计模式:单例模式的深入理解与应用
【10月更文挑战第22天】 在软件开发中,设计模式是解决特定问题的通用解决方案。本文将通过通俗易懂的语言和实例,深入探讨PHP中单例模式的概念、实现方法及其在实际开发中的应用,帮助读者更好地理解和运用这一重要的设计模式。
14 1
|
1月前
|
设计模式 存储 数据库连接
PHP中的设计模式:单例模式的深入解析与实践
在PHP开发中,设计模式是提高代码可维护性、扩展性和复用性的关键技术之一。本文将通过探讨单例模式,一种最常用的设计模式,来揭示其在PHP中的应用及优势。单例模式确保一个类仅有一个实例,并提供一个全局访问点。通过实际案例,我们将展示如何在PHP项目中有效实现单例模式,以及如何利用这一模式优化资源配置和管理。无论是PHP初学者还是经验丰富的开发者,都能从本文中获得有价值的见解和技巧,进而提升自己的编程实践。
|
1月前
|
设计模式 安全 Java
C# 一分钟浅谈:设计模式之单例模式
【10月更文挑战第9天】单例模式是软件开发中最常用的设计模式之一,旨在确保一个类只有一个实例,并提供一个全局访问点。本文介绍了单例模式的基本概念、实现方式(包括饿汉式、懒汉式和使用 `Lazy<T>` 的方法)、常见问题(如多线程和序列化问题)及其解决方案,并通过代码示例详细说明了这些内容。希望本文能帮助你在实际开发中更好地应用单例模式,提高代码质量和可维护性。
29 1
|
1月前
|
设计模式 缓存 数据库连接
探索PHP中的设计模式:单例模式的实现与应用
在PHP开发中,设计模式是提高代码可复用性、可维护性和扩展性的重要工具。本文将深入探讨单例模式(Singleton Pattern)的基本概念、在PHP中的实现方式以及实际应用场景。单例模式确保一个类仅有一个实例,并提供全局访问点。通过具体代码示例和详细解释,我们将展示如何在PHP项目中有效利用单例模式来解决实际问题,提升开发效率和应用性能。
|
1月前
|
设计模式 存储 测试技术
PHP中的设计模式:单例模式的深入解析与实践
在PHP开发领域,设计模式是解决常见问题的最佳实践。本文将深入探讨单例模式,一种确保类只有一个实例的设计模式,并提供实际应用示例。我们将从单例模式的基本概念讲起,通过实际案例展示如何在PHP中实现单例模式,以及它在不同场景下的应用和优势。最后,我们会探讨单例模式的优缺点,帮助开发者在实际项目中做出明智的选择。
|
1月前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP开发领域,设计模式是解决常见问题的高效方案集合。它们不是具体的代码,而是一种编码和设计经验的总结。单例模式作为设计模式中的一种,确保了一个类仅有一个实例,并提供一个全局访问点。本文将深入探讨单例模式的基本概念、实现方式及其在PHP中的应用。
单例模式在PHP中的应用广泛,尤其在处理数据库连接、日志记录等场景时,能显著提高资源利用率和执行效率。本文从单例模式的定义出发,详细解释了其在PHP中的不同实现方法,并探讨了使用单例模式的优势与注意事项。通过对示例代码的分析,读者将能够理解如何在PHP项目中有效应用单例模式。
|
1月前
|
设计模式 存储 数据库连接
PHP中的设计模式:单例模式的深入探讨与实践
在PHP开发领域,设计模式是提升代码可读性、可维护性和扩展性的重要工具。本文聚焦于单例模式——一种确保类只有一个实例,并提供全局访问点的设计模式。我们将从定义、实现方式、应用场景以及在PHP框架中的运用等方面进行详细探讨,旨在帮助PHP开发者更好地理解和运用单例模式。
|
24天前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
24 0