likes
comments
collection
share

第一课:单例模式 | 创建型模式

作者站长头像
站长
· 阅读数 2

嗨大家好,欢迎来到风筝的设计模式专栏。我相信快节奏的生活下,文字的力量依然强大! 上节课带读者认识了设计模式。今天我们来讲设计模式中的单例模式。开整!

  • 创建型模式是一种常见的设计模式,它关注如何创建对象的问题,并且能够帮助我们在创建对象时更加灵活、方便地控制对象的生成过程。同时,创建型模式也可以帮助我们减少代码的冗余度,提高代码的可读性和可维护性。

一、什么是单例模式?

单例模式是一种创建型设计模式,它可以确保一个类只有一个实例,并提供一个全局访问点来访问该实例。换句话说,单例模式可以让你在应用程序中创建全局唯一的对象。

二、为什么需要单例模式?

在许多应用程序中,我们需要确保某些对象只有一个实例。比如,在一个 Web 应用程序中,一个数据库连接池对象就可以被设计成单例模式。这样就可以确保每个请求都使用同一个数据库连接池对象,从而避免因频繁创建数据库连接池对象而导致的系统性能下降。

另外,单例模式还可以帮助我们完成懒加载 (lazy loading) 和节约系统资源的重要任务。

三、单例模式的实现

要实现单例模式,我们需要注意以下两个问题:

  1. 如何确保一个类只有一个实例?
  2. 如何在整个应用程序中访问该实例?

1. 如何确保一个类只有一个实例?

在 Java 中,单例模式的实现方式通常有两种:饿汉式 (Eager Initialization) 和懒汉式 (Lazy Initialization)。

饿汉式单例模式

饿汉式单例模式是指在类加载时就创建好了一个静态实例,保证了线程安全性。其代码示例如下:

java复制代码
public class Singleton {
    // 在类加载时就创建好了一个静态实例
    private static Singleton instance = new Singleton();

    private Singleton() {
        // 私有化构造方法,防止外界直接实例化该类
    }

    public static Singleton getInstance() {
        return instance;
    }
}

懒汉式单例模式

懒汉式单例模式是指只有在需要用到实例时才去创建它,这样可以节省系统资源。但是懒汉式单例模式在多线程环境下可能会出现竞争条件,需要注意线程安全问题。其代码示例如下:

java复制代码
public class Singleton {
    private static Singleton instance;

    private Singleton() {
        // 私有化构造方法,防止外界直接实例化该类
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

静态内部类

另外,除了上述提到的饿汉式和懒汉式单例模式之外,还有一种线程安全的方式是利用静态内部类来实现单例,这种方式既能确保线程安全,又能实现懒加载。具体实现如下:

java复制代码
public class Singleton {

    private Singleton() {}

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

非常简洁明了,而且也非常安全可靠,推荐使用。

2. 如何在整个应用程序中访问该实例?

为了确保我们在整个应用程序中可以访问到该实例,我们需要为单例模式提供一个全局访问点。一般来说,我们使用静态方法来实现这个全局访问点。具体代码示例如下:

java复制代码
public class Singleton {
    private static Singleton instance;

    private Singleton() {
        // 私有化构造方法,防止外界直接实例化该类
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    public void doSomething() {
        // 这里是单例对象要执行的操作
    }
}

四、单例模式的优缺点

1. 优点

  • 单例模式可以确保一个类只有一个实例。
  • 单例模式可以节约系统资源,避免因频繁创建对象而导致的内存开销过大问题。
  • 单例模式提供了一个全局访问点,方便我们在整个应用程序中访问该实例。

2. 缺点

  • 单例模式会使代码更加复杂。因为它需要对多线程环境做出考虑,因此可能需要使用到双重检查锁定 (Double-check Locking)、volatile 等技术。
  • 单例模式可能会降低代码的可测试性。因为它可能会在测试过程中产生一些不必要的依赖关系,从而使得测试变得困难。

五、如何使用单例模式?

在面向对象编程中,单例模式是一个非常常见和实用的设计模式。以下是单例模式的使用步骤:

  1. 定义一个私有的构造方法,防止外界直接实例化该类。
  2. 声明一个私有的静态变量,用于保存该类的唯一实例。
  3. 提供一个公有的静态方法来获取该实例。
  4. 在该方法中实现对实例化的控制,使得每次获取到的都是同一个实例。

代码示例:

java复制代码
public class Singleton {
    private static Singleton instance;

    private Singleton() {
        // 私有化构造方法,防止外界直接实例化该类
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    public void doSomething() {
        // 这里是单例对象要执行的操作
    }
}

在需要使用该单例对象的场景下,我们可以通过静态方法 getInstance() 来获取该实例,从而调用它的各种方法。例如:

java复制代码
public class Test {
    public static void main(String[] args) {
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();

        System.out.println(s1 == s2); // 输出 true,说明 s1 和 s2 指向的是同一个对象
    }
}

六、小结

以上就是关于单例模式的详细介绍和示例代码。在实际编程中,单例模式是一个非常常见和实用的设计模式,在需要保证全局唯一性且节省系统资源时可以考虑使用。但是,我们需要注意单例模式的优缺点,避免过度使用它,以免造成代码的不必要复杂性。