首页 > 其他分享 >软件设计模式-单例模式

软件设计模式-单例模式

时间:2024-09-12 21:29:02浏览次数:1  
标签:Singleton 软件设计 模式 int 枚举 实例 单例 public

单例模式(Singleton Pattern)是创建型设计模式的一种,旨在确保一个类在整个应用程序运行期间只有一个实例,并提供全局访问点来获取该实例。这种模式对于那些希望在整个系统中共享唯一对象的场景非常有用,比如数据库连接、日志系统、配置管理器等。

单例模式的核心要点
唯一实例:类只能有一个实例,不能被重复创建。
全局访问点:提供一个静态方法用于获取该唯一实例,从而保证全局范围内都可以访问到它。
单例模式的实现步骤
私有构造函数:通过将构造函数设为 private,防止外部类通过 new 操作符创建该类的实例。
静态变量存储唯一实例:使用一个静态变量来存储该类的唯一实例。
静态方法获取实例:通过一个公共的静态方法提供对外访问该实例的方法,确保每次获取的都是同一个实例。
单例模式的实现方式
单例模式有多种实现方式,其中常见的有懒汉式和饿汉式。此外,还可以使用双重检查锁定和枚举等方式来实现线程安全的单例。

  1. 懒汉式单例(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;
}

}
优点:实现简单,线程安全。 缺点:类加载时就创建实例,如果实例不被使用会浪费资源。

  1. 静态内部类实现单例(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;
}

}
优点:既实现了延迟加载,又保证了线程安全,推荐使用这种方式。

  1. 枚举实现单例(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);
}

}
枚举的高级功能

  1. 枚举可以实现接口
    枚举可以实现接口,使得可以为每个枚举常量定义不同的行为。

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));
}
}

标签:Singleton,软件设计,模式,int,枚举,实例,单例,public
From: https://www.cnblogs.com/torrentgz/p/18411100

相关文章

  • 软件设计模式-生成器模式
    生成器模式的结构生成器(Builder):提供构建产品各部分的方法,一般是一步一步构建复杂对象的各个部分。具体生成器(ConcreteBuilder):实现生成器接口,构建和装配具体的产品部件。产品(Product):最终生成的复杂对象。指挥者(Director):负责安排构建步骤,控制生成器构建对象的过程(可选)。客户端......
  • 软件模式-原型模式
    原型模式的核心思想原型模式的核心是使用一个原型接口来定义一个克隆方法,该方法允许对象自身进行复制。通过这个克隆方法,可以快速生成一个与原型对象相同的实例,而不需要直接创建新对象并手动设置属性。原型模式的结构原型接口(Prototype):定义一个clone()方法,用于克隆对象。具......
  • Java设计模式之责任链模式详细讲解和案例示范
    在本文中,我们将详细讲解Java设计模式中的责任链模式,探讨其基本概念、使用场景、常见问题和解决方式。同时,我们还会介绍责任链模式与策略模式的区别,并结合电商交易系统的示例进行说明。此外,我们还会探讨责任链模式在开源框架中的应用。1.责任链模式概述责任链模式是一种行......
  • 两种消息传递模式:发布订阅模式,排队模式
    Kafka是一种分布式流处理平台,支持多种消息传递模式,其中最主要的两种模式是发布-订阅(Pub-Sub)和排队(Queueing)。具体来说,Kafka的设计和实现允许它灵活地支持这两种模式。发布-订阅(Pub-Sub)模式在Kafka中,主题(Topic)是发布-订阅模式的核心概念:Producer(生产者)将消息发布到一个或多个......
  • 【软件设计师真题】下午题第二大题---数据库设计
    系列文章目录1.【软考之软件设计师】PPT课件2.【软考之软件设计师】学习笔记3.【软件设计师真题】下午题第一大题—数据流图设计4.【软件设计师真题】下午题第二大题—数据库设计5.【软件设计师真题】下午题第三大题—UML分析与设计6.【软件设计师真题】下午题......
  • 搭建线上扭蛋机小程序,企业新的盈利模式?
    近几年,随着市场对潮玩商品的需求不断增加,越来越多的资本入局到潮玩市场,因此,扭蛋机也开始在市场中持续走红,扭蛋机的各种创新玩法,也刺激着消费者的购买欲望,推动市场的发展。扭蛋机的目标群体主要是年轻人,具备较高的消费能力,同时当下年轻人的消费习惯主要集中于线上,这也为扭蛋机的转型......
  • Edge浏览器设置夜间模式/深色模式
    问题背景普通白色背景感觉有点刺眼,想改成深色背景,但是默认的设置里面只能修改边框的颜色:这里虽然设置界面和边框变成了黑色的,但是实际上打开网页还是白色的。全局配置在Edge浏览器打开edge://flags/,然后搜索DarkMode,从中选取对应的模式,可以直接Enable,我使用的配置为:配......
  • 信号发生器在扫描模式下输出正弦波信号,示波器呈现的波形显示异常与不理想,这是为什么
    如下图所示,在信号发生器扫描模式下输出正弦波信号,示波器呈现出的波形显示“异常”“不理想”情况,其原因可能与以下因素有关:1、扫描速度与示波器刷新率不匹配如果信号发生器的扫描速率(频率变化速度)与示波器的时间基准或刷新率不同步,示波器可能无法正确显示动态变化的频率信号......
  • 软件设计师中级(程序语言)
    目录一、程序设计语言概述1.低级语言与高级语言2.程序设计语言发展概述3.程序设计语言杂论4.程序设计语言的基本成分5.函数二、汇编、编译、解释1.汇编程序基本原理2.编译程序基本原理3.解释程序基本原理4.编译与解释比较三、文法分析1.正规式2.有限自动机3.上......
  • 57.C文件操作有关常用函数和模式整理
    为方便而有所整理数据文件分为文本文件二进制文件求速且生成文件较小则用二进制文件保存数据若要无须经过任何转换就可看到内容用文本文件保存数据FILE*gao=fopen("C:\\Users\\Desktop\\gao.txt","模式");fopen两个参数1个要打开文件的路径2打开的模式方式......