独领风骚:单例模式

news/2024/7/20 13:47:46 标签: java, 内存管理

作者:Jeff Lee 出处:http://www.cnblogs.com/Alandre/ 欢迎转载,也请保留这段声明。谢谢!

系列文章:[传送门]

 

  单例模式(Singleton)可以说是最简单的模式,对.net来说,因为不需要考虑到垃圾回收机制,实现起来很简单,但是对于没有提供内存管理的平台来说,比如C++,因为单例模式只考虑创建对象,所以使用的时候要考虑全面些。Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。

 

案例有如下:

    单一的程序属性文件
    一个系统唯一的回收站

单例模式的结构

    

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

java中实现单例模式

饿汉单例类

/**
 * 饿汉单例类
 * #由于构造函数是私有的,此类不会被继承,也不会被外界直接创建任意多的实例。
 * @author Li
 */
public class EagerSingleton {
    private static final EagerSingleton m_instance =  new EagerSingleton();
    
    /**
     * 私有的默认构造子
     */
    private EagerSingleton()
    {
    }
    
    /**
     * 静态工厂方法
     */
    public static EagerSingleton getInstance()
    {
        return m_instance;
    }
 
}
#由于构造函数是私有的,此类不会被继承,也不会被外界直接创建任意多的实例。

 

懒汉式单例类

public class Singleton {
  private static Singleton instance = null;

  public static synchronized Singleton getInstance() {

  if (instance==null)
    instance=new Singleton();
  return instance;   }

}

 #synchronized:关键字,代表这个方法加锁

#懒汉式的区别,只有第一次调用后才会有个实例出来。

登记式单例类

import java.util.HashMap;
import java.util.Map;
//登记式单例类.
//类似Spring里面的方法,将类名注册,下次从里面直接获取。
public class Singleton3 {
    private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
    static{
        Singleton3 single = new Singleton3();
        map.put(single.getClass().getName(), single);
    }
    //保护的默认构造子
    protected Singleton3(){}
    //静态工厂方法,返还此类惟一的实例
    public static Singleton3 getInstance(String name) {
        if(name == null) {
            name = Singleton3.class.getName();
            System.out.println("name == null"+"--->name="+name);
        }
        if(map.get(name) == null) {
            try {
                map.put(name, (Singleton3) Class.forName(name).newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return map.get(name);
    }
    //一个示意性的商业方法
    public String about() {    
        return "Hello, I am RegSingleton.";    
    }    
    public static void main(String[] args) {
        Singleton3 single3 = Singleton3.getInstance(null);
        System.out.println(single3.about());
    }
}

.NET 单例实践

.net中解决线程安全的问题也很简单,就是用lock锁。摘自我的小伙伴:http://www.cnblogs.com/xishuai/p/3509346.html

public class SingletonTest
    {
        private static SingletonTest singleton;
        private static readonly object syncObject = new object();
        /// <summary>
        /// 构造函数必须是私有的
        /// 这样在外部便无法使用 new 来创建该类的实例
        /// </summary>
        private SingletonTest()
        { }
        /// <summary>
        /// 定义一个全局访问点
        /// 设置为静态方法
        /// 则在类的外部便无需实例化就可以调用该方法
        /// </summary>
        /// <returns></returns>
        public static SingletonTest getSingleton()
        {
            //这里可以保证只实例化一次
            //即在第一次调用时实例化
            //以后调用便不会再实例化
            //第一重 singleton == null
            if (singleton == null)
            {
                lock (syncObject)
                {
                    //第二重 singleton == null
                    if (singleton == null)
                    {
                        Console.WriteLine(String.Format("我是被线程:{0}创建的!", Thread.CurrentThread.Name));
                        singleton = new SingletonTest();
                    }
                }
            }
            return singleton;
        }
    }

 

总结 

  单例模式优点

    一、实例控制
      单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
    二、灵活性
      因为类控制了实例化过程,所以类可以灵活更改实例化过程。
 

  单例模式缺点

    一、开销
      虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
    二、可能的开发混淆
      使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用 new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
    三、对象生存期
      不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。

 

感谢及资源共享

    

    路上走来一步一个脚印,希望大家和我一起。

    感谢读者!很喜欢你们给我的支持。如果支持,点个赞。

    知识来源: http://book.douban.com/doulist/3942229/

 

 

转载于:https://www.cnblogs.com/Alandre/p/3674645.html


http://www.niftyadmin.cn/n/1119648.html

相关文章

一行或者多行文字与按钮垂直居中

第一种css写法&#xff1a; 第二种: html&#xff1a; 转载于:https://www.cnblogs.com/weiyf/p/9706828.html

拼接播放地址_杰和科技G330六屏拼接主机带来差异化6屏拼接方案

原标题&#xff1a;杰和科技G330六屏拼接主机带来差异化6屏拼接方案蓬勃复苏商业零售产业&#xff0c;伴随着商业营销体系的日趋成熟&#xff0c;展示产品的手段也同时变得合理、高效。我们也可以注意到&#xff0c;越来越多的餐饮、服饰类零售店铺开始使用超大展示广告屏&…

hammerdb mysql_for Mysql_鲲鹏数据库解决方案_测试指导_HammerDB测试指导书_故障排除_华为云...

在数据库服务器上创建库并按测试模型建表&#xff0c;可在HammerDB安装路径下的src/mysql/mysqlolap.tcl中查看OLAP测试脚本。建表(默认行存)&#xff1a;--建tpch数据库及表,添加主键和外键CREATE DATABASE mysql_tpch;USE mysql_tpch;CREATE TABLE REGION (R_REGIONKEY INT N…

web前端页面水印的实现,防手动删除和修改,支持vue3.0+vite项目

一、实现思路 因为之前负责过公司的后端平台建设&#xff0c;有很多敏感信息&#xff0c;所以有了给前端页面加水印的需求。网上看了一些案例&#xff0c;其实道理都一样&#xff0c;在这里简单记录一下。 1、创建画布 首先&#xff0c;想要绘制水印&#xff0c;我们第一步要创…

如何将自己的插件发布到npm上 / 发布到公司npm源上

一、项目初始化 新建一个空文件夹&#xff0c;存放你的插件源代码。 然后执行npm init&#xff0c;初始化项目的一些基本信息。 然后你会发现项目中多了一个package.json的文件。 二、编写插件内容 我们先写一个简单的测试例子。 在根目录新建一个index.js文件&#xff0…

ado execute open区别_红米note9pro对比note9promax区别在哪 参数配置对比

红米note9pro对比note9promax区别在哪 参数配置对比红米Note9系列将会推出三款机型&#xff0c;那么红米Note9Pro和红米Note9ProMax有哪些区别呢&#xff0c;在配置有什么差距呢&#xff0c;接下来小编就从不同的角度进行对比一下&#xff0c;一起看看吧&#xff01;一、主要参…

SylixOS 下的IO系统调用

SylixOS标准I/O基本介绍1.1 简介I/O 系统又称作输入输出系统&#xff0c;SylixOS 兼容POSIX标准输入输出系统&#xff0c;SylixOS的I/O概念继承了UNIX操作系统的I/O概念&#xff0c;认为一切皆为文件。与UNIX操作系统相同&#xff0c; SylixOS中的文件也分为不同的类型。1.2 两…

java 模块优化_多模块下Gradle优化(一)

在项目开发中,往往会用到很多个module,每个module都有自己的gradle,而这些gradle很大部分都是重复的,所以我们可以将重复的部分,抽取成一个公共的gradle,然后各个module都引用这个公共中的就可以了一个项目中,gradle总共有三类,setting.gradle, build.gradle和各个module下的bu…