软件设计模式-单例模式
单例模式(Singleton Pattern)是创建型设计模式的一种,旨在确保一个类在整个应用程序运行期间只有一个实例,并提供全局访问点来获取该实例。这种模式对于那些希望在整个系统中共享唯一对象的场景非常有用,比如数据库连接、日志系统、配置管理器等。
单例模式的核心要点
唯一实例:类只能有一个实例,不能被重复创建。
全局访问点:提供一个静态方法用于获取该唯一实例,从而保证全局范围内都可以访问到它。
单例模式的实现步骤
私有构造函数:通过将构造函数设为 private,防止外部类通过 new 操作符创建该类的实例。
静态变量存储唯一实例:使用一个静态变量来存储该类的唯一实例。
静态方法获取实例:通过一个公共的静态方法提供对外访问该实例的方法,确保每次获取的都是同一个实例。
单例模式的实现方式
单例模式有多种实现方式,其中常见的有懒汉式和饿汉式。此外,还可以使用双重检查锁定和枚举等方式来实现线程安全的单例。
- 懒汉式单例(Lazy Initialization)
懒汉式单例在第一次使用时才创建实例,即实例的创建是延迟的。该实现方式避免了类加载时就创建实例,但需要注意线程安全问题。
复制代码
public class Singleton {
// 静态变量存储唯一实例,初始值为null
private static Singleton instance = null;
// 私有构造函数,防止外部创建实例
private Singleton() {}
// 公共静态方法,返回唯一实例
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton(); // 第一次调用时创建实例
}
return instance;
}
}
问题:上述懒汉式实现方式不是线程安全的。在多线程环境中,多个线程可能同时调用 getInstance(),导致创建多个实例。
饿汉式单例(Eager Initialization)
饿汉式单例在类加载时就创建实例,不管是否会使用到。这种方式是线程安全的,但如果实例创建的开销较大且应用程序一直未使用该实例,可能会浪费资源。
java
复制代码
public class Singleton {
// 在类加载时就创建实例
private static final Singleton instance = new Singleton();
// 私有构造函数
private Singleton() {}
// 返回已创建的实例
public static Singleton getInstance() {
return instance;
}
}
优点:实现简单,线程安全。 缺点:类加载时就创建实例,如果实例不被使用会浪费资源。
- 静态内部类实现单例(Static Inner Class Singleton)
使用静态内部类的方式既保证了延迟加载,又能够保证线程安全。静态内部类在被使用时才会被加载,且类加载是线程安全的。
java
复制代码
public class Singleton {
private Singleton() {}
// 静态内部类,持有 Singleton 的实例
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
// 通过静态内部类获取唯一实例
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
优点:既实现了延迟加载,又保证了线程安全,推荐使用这种方式。
- 枚举实现单例(Enum Singleton)
使用枚举类型实现单例模式是最简洁和安全的方式,因为枚举类型本身就是线程安全的,并且可以防止通过反序列化创建新的实例。
java
复制代码
public enum Singleton {
INSTANCE;
public void doSomething() {
System.out.println("Singleton using Enum.");
}
}
优点:枚举方式实现的单例模式是防反射、防序列化破解单例的最佳方式。
单例模式的优点
唯一实例:确保系统中只有一个对象,节省内存和资源。
全局访问:通过统一的静态方法提供全局访问点,简化访问。
延迟加载:可以通过懒汉式实现延迟实例化,避免不必要的资源消耗。
线程安全:可以通过适当的同步机制确保在多线程环境下的正确性。
单例模式的缺点
全局状态可能导致问题:由于单例模式提供全局访问点,可能导致不良的全局状态,使代码难以测试和维护。
难以扩展:单例模式的类通常很难扩展,因为它不能被轻易地修改或替换。
枚举(Enum)是Java中的一种特殊类型,它用于定义一组固定的常量,表示一类相似的值。每个枚举常量都是该枚举类型的实例,枚举常用于表示状态、选项或具有固定数量的属性值。枚举类型在Java中通过 enum 关键字定义,并且是 java.lang.Enum 类的子类。
Java枚举的特点
常量的集合:枚举中的值是有限的、固定的,不能被改变。
类型安全:每个枚举常量都是一个具体的实例,并且是类型安全的,可以避免在代码中使用常量时可能出现的错误。
可以包含字段、方法:枚举不仅仅是常量集合,还可以包含字段、方法和构造函数,使其具备类的某些功能。
可以实现接口:枚举可以实现接口,但不能继承其他类(因为枚举隐式继承自 java.lang.Enum 类)。
带有字段和构造函数的枚举
java
复制代码
public enum Color {
RED("#FF0000"), GREEN("#00FF00"), BLUE("#0000FF");
private String hexCode;
// 枚举的构造函数,必须是 private
private Color(String hexCode) {
this.hexCode = hexCode;
}
// 获取颜色的十六进制代码
public String getHexCode() {
return hexCode;
}
}
在这个例子中,Color 枚举表示颜色,每个颜色都有一个对应的十六进制代码。你可以通过 getHexCode() 方法来获取每个枚举常量的颜色代码。
使用带有方法的枚举
java
复制代码
public class Main {
public static void main(String[] args) {
Color color = Color.RED;
System.out.println("Color: " + color);
System.out.println("Hex Code: " + color.getHexCode());
}
}
输出:
less
复制代码
Color: RED
Hex Code: #FF0000
枚举中的方法
除了自定义方法外,Java 枚举还提供了一些常用的方法:
values():返回枚举常量的数组。
valueOf(String name):根据名称返回对应的枚举常量。
name():返回枚举常量的名称。
ordinal():返回枚举常量的序数(从 0 开始)。
示例:
java
复制代码
public class Main {
public static void main(String[] args) {
// 使用 values() 方法
for (Day day : Day.values()) {
System.out.println(day + " is at index " + day.ordinal());
}
// 使用 valueOf() 方法
Day day = Day.valueOf("MONDAY");
System.out.println("Day: " + day);
}
}
枚举的高级功能
- 枚举可以实现接口
枚举可以实现接口,使得可以为每个枚举常量定义不同的行为。
java
复制代码
interface Operation {
int apply(int a, int b);
}
public enum Calculator implements Operation {
ADD {
@Override
public int apply(int a, int b) {
return a + b;
}
},
SUBTRACT {
@Override
public int apply(int a, int b) {
return a - b;
}
},
MULTIPLY {
@Override
public int apply(int a, int b) {
return a * b;
}
},
DIVIDE {
@Override
public int apply(int a, int b) {
return a / b;
}
};
}
使用枚举实现的接口
java
复制代码
public class Main {
public static void main(String[] args) {
int a = 10, b = 5;
System.out.println("Add: " + Calculator.ADD.apply(a, b));
System.out.println("Subtract: " + Calculator.SUBTRACT.apply(a, b));
}
}
本文作者:torrentgz
本文链接:https://www.cnblogs.com/torrentgz/p/18411100
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步