单例模式是使用最为普遍的模式之一。它属于创建模式,确保系统中该类型的类只被实例化一次。 也许有误解,认为单例是在jvm进程中只有一个实例,其实是在同一个Classloader下面仅被实例化一次。Singleton通常用来表示本质上唯一的系统组件,比如文件系统,窗口管理器,系统全局的配置之类的。 在Java语言中,单例能带来一些好处: 1. 对于频繁使用的对象,可以省略创建对象所花费的时间,特别对于重量级的对象,可以节省很大的开销。 2. 有new操作的次数减少,对内存的使用频率也会有所降低,减轻GC的负担。 让我们来看单例的一些实现:
实现方法(1):
- public class Singleton {
-
- private static final Singleton INSTANCE = new Singleton();
-
- private Singleton(){
-
- }
-
- public static Singleton getInstance(){
- return INSTANCE;
- }
-
- }
私有构造器仅被调用一次,由于没有公有的构造器,防止客户端实例化该对象。对于静态方法getInstance的调用都会返回同一个对象,final保证了引用不变。除非享有特权的客户端可以通过反射机制,借助AccessableObject.setAccessible方法调用私有构造器。
这种实现比较简洁,但无法做到延迟加载,因为instance是static的,实例化之类加载的时候就发生了。如果单例的创建过程非常慢,耗费资源,就可以考虑lazy-initialize的方式。
- public class Singleton {
-
- private static Singleton INSTANCE = null;
-
- private Singleton(){
-
- }
-
- public static synchronized Singleton getInstance(){
- if(INSTANCE == null){
- INSTANCE = new Singleton();
- }
- return INSTANCE;
- }
-
- }
对于静态域INSTANCE,去掉了关键字final,并且初始值为null,确保系统启动时没有额外的负载,在getInstance判断是否没有实例化,如果没有则创建实例,这里给方法加上了synchronized关键字,防止多个线程同时判断到实例为空,创建多个实例。但同步关键可能也会引来性能问题。
让我们看一下改进的版本:
- public class Singleton {
-
- private Singleton(){
-
- }
-
- private static class SingletonHolder{
- private static Singleton INSTANCE = new Singleton();
- }
-
- public static synchronized Singleton getInstance(){
- return SingletonHolder.INSTANCE;
- }
-
- }
这种使用内部类的维护单例,确保只有SingletonHolder类被加载才会初始化,实例发生在加载时,对多线程友好。
上面的情形没有考虑到序列化问题,当Singleton实现了Serilaizable接口时,在反序列化阶段可能由于反射机制创建多个实例。为防止这种意外可以加上readResolve函数:
- private Object readResolve(){
- return SingletonHolder.INSTANCE;
- }
对于1.5以后的java版本,我们可以借助于单元素的枚举实现单例,如下:
- public enum SingletonEnum {
- INSTANCE("name");
-
- private String name;
-
- private SingletonEnum(String name){
- this.name = name;
- }
- }
这种实现极为简洁,无偿的提供序列化机制,不妨可以尝试这种方式。
分享到:
相关推荐
这份“程序设计经验杂谈”文档,据说是出自一位大师之手,无疑为我们提供了宝贵的洞见。在本文中,我们将探讨几个关键的程序设计经验,希望能对你在编程旅程中提供一些帮助。 首先,我们来谈谈问题解决策略。在编程...
例如,单例模式在资源管理类(如数据库连接池)中非常常见,它确保整个应用只有一个实例存在。工厂方法则允许我们在不修改原有代码的基础上,通过扩展新增对象类型。适配器模式可以将不兼容的接口转换为可协作的形式...
计算机汇编杂谈-理解其中的原理
标题中的“杂谈----1 显示横向滚动条”暗示了我们将会探讨的是关于在界面设计中如何实现或处理横向滚动条的技术问题。这通常涉及到前端开发,特别是网页或应用程序的用户界面(UI)部分,其中可能包括HTML、CSS和...
这篇“Android杂谈---Nexus S的ROOT教程”显然是针对想要获取Nexus S手机ROOT权限的用户,提供了一条详细的操作路径。Nexus S是由Google与三星联合推出的旗舰设备,因其开源特性而深受开发者喜爱。 首先,我们需要...
"项目管理故事2-实施策略杂谈-开元项目实施" 本文是基于赵磊项目经理的项目管理故事,分享实施成功经验。赵磊担任过多个项目经理职位,负责开元旅业NC项目财务实施、苏州好孩子NC财务项目实施、合肥公交NC财务第一...
「安全管理」Linux_HIDS杂谈 - WEB应用防火墙 安全管理 安全资讯 安全开发 零信任 身份管理
3. **模型-视图-控制器(MVC)模式**: Swing设计时遵循MVC模式,组件如JTable和JList采用此模式,将数据(模型)与显示(视图)分离,允许独立更新和定制。例如,通过DefaultListModel管理JList的数据模型。 4. **...
2. **Android Studio Profiler**:在Android Studio中,性能分析器提供了电池监控功能,可以帮助我们查看Doze模式和App Standby对应用的影响。 3. **第三方工具**:如`Alarm Tester`这样的应用可以帮助测试闹钟的...
例如,工厂模式用于创建对象,单例模式确保类只有一个实例,而观察者模式则用于实现对象之间的松耦合通信。理解和熟练运用这些模式能提高代码的复用性和扩展性。 其次,算法是解决问题的基础工具,熟练掌握排序、...
它涵盖了程序设计语言、数据库技术、软件开发工具、系统平台、标准制定以及设计模式等多个方面。 - **软件名称的由来**:软件一词的诞生与硬件相对应,硬件是指计算机系统中的物理设备,如CPU、内存等,而软件则是指...
3. **灵活性**:C 语言提供了对硬件底层的直接访问能力,这使得开发者可以直接控制内存和其他硬件资源,这对于嵌入式系统的设计和优化至关重要。 4. **可移植性**:由于 C 语言标准相对统一,代码可以从一个平台轻松...
它由可配置逻辑模块CLB、输出输入模块IOB和内部连线组成,允许用户通过逻辑设计和时序约束来实现复杂的数字系统。FPGA的优势在于其灵活性和高速并行处理能力,适用于需要快速原型验证、实时系统和高度定制化应用的...
在设计过程中,FPGA允许工程师通过原理图输入或硬件描述语言进行设计,然后通过软件仿真验证其正确性,大大缩短了设计周期,减少了PCB面积,提高了系统的可靠性。 相反,DSP是一种专门用于数字信号处理的微处理器,...
Java的动态加载机制是其设计的一大亮点,它允许程序在运行时按需加载类,而不是一次性加载所有类。这种机制降低了内存消耗,并提高了程序的灵活性。当我们编写Java程序并运行时,只有当我们实际创建一个类的实例或者...