scala实现单例模式

单例模式介绍

单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。

对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。

单例模式七种写法

第一种(懒汉,线程不安全)

public class Singleton {
    private static Singleton instance;
    private Singleton (){}

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

不适合多线程。

第二种(懒汉,线程安全)

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

这种方式线程安全,但是效率很低。

第三种(饿汉)

public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton (){}
    public static Singleton getInstance() {
	return instance;
    }
}

这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。

第四种(饿汉,变种)

public class Singleton {
    private Singleton instance = null;
    static {
	instance = new Singleton();
    }
    private Singleton (){}
    public static Singleton getInstance() {
	return this.instance;
    }
}

和第三种差不多,都是在类初始化即实例化instance。

第五种(静态内部类)

public class Singleton {
    private static class SingletonHolder {
	private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton (){}
    public static final Singleton getInstance() {
	return SingletonHolder.INSTANCE;
    }
}

这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,它跟第三种和第四种方式不同的是(很细微的差别):第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方式就显得很合理。

第六种(枚举)

public enum Singleton {
    INSTANCE;
    public void whateverMethod() {
    }
}

这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊,不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏,在实际工作中,我也很少看见有人这么写过。

第七种(双重校验锁)

public class Singleton {
    private volatile static Singleton singleton;
    private Singleton (){}
    public static Singleton getSingleton() {
	if (singleton == null) {
	    synchronized (Singleton.class) {
		if (singleton == null) {
		    singleton = new Singleton();
		}
	    }
	}
	return singleton;
    }
}

第二种的升级版,俗称双重检查锁定。

scala单例

单例模式就控制类实例的个数,通过伴生对象来访问类的实例就提供了控制实例个数的机会。一个简单示例:

class Worker private{
  def work() = println("I am the only worker!")
}

object Worker{
  val worker = new Worker
  def GetWorkInstance() : Worker = {
    worker.work()
    worker
  }
}

object Job{
  def main(args: Array[String]) {
		for (i <- 1 to 5) {
		  Worker.GetWorkInstance();
		}
	}
}

class Worker private声明了Worker的首构造函数是私有的,这样Worker的所有构造函数都不能直接被外部调用,因为所有从构造函数都会首先调用其他构造函数(可以是主构造函数,也可以是从构造函数),结果就是主构造函数是类的唯一入口点。

另一方面,Worker.GetWorkInstance();有点类似静态函数调用,但在Scala中这是不对的。Scala会隐式地调用apply来创建一个伴生对象的实例。Scala是一个纯粹的面向对象语言,不允许有任何破坏对象模型的机制存在,比如类的静态变量、函数等。

作者:skyme

联系方式:

邮箱【cloudskyme@163.com】

QQ【270800073】

本文版权归作者和共同所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

时间: 2024-10-16 05:02:59

scala实现单例模式的相关文章

scala 学习笔记(04) OOP(上)主从构造器/私有属性/伴生对象(单例静态类)/apply方法/嵌套类

一.主从构造器 java中构造函数没有主.从之分,只有构造器重载,但在scala中,每个类都有一个主构造器,在定义class时,如果啥也没写,默认有一个xxx()的主构造器 class Person { var name: String = _ /** * 从构造器 * @param name */ def this(name: String) = { this //注意:从构造器,必须先调用主构造器 this.name = name; } override def toString = { "

Scala 语法

下面的代码包含了基本的Scala的语法内容.包括:判断,循环代码片段,方法定义,调用. 虚拟类,继承,接口,case,package,单例模式 [java] view plain copy   package org.exinglo.scala      class LearnScala {      }      object Test{     val variable1 = "this is my first scala variable"            def func

学习Scala第一篇-从hello World开始

最近开始系统性的学习scala.其实之前使用过scala的,比如我在用Gatling这款性能测试工具的时候就接触到了scala了.Gatling本身就是用Scala写的,而且Gatling的性能测试配置文件本身就是一个scala类,可以随意使用scala甚至是Java提供的各种类库.当时觉得用Gatling特别舒服的原因就在于配置文件强大的表现力.而这种表现力就是由Scala语言提供的. 言归正传,学习Scala还是从最简单的Hello world开始.在Scala官网中显著的标题就是: Obj

Scala简单编程

1. Scala简单概述Scala是多范式编程语言,其设计的初衷是要集成面向对象编程和函数式编程以及各种特性.需要说明的一点是: Scala是基于java平台(JVM) ,并兼容现有的Java程序下面是Scala官方网址http://www.scala-lang.org/ 2.Scala编译器安装 安装JDK因为Scala是运行在JVM平台,所以这里JDK是必需的 安装Scala访问上面提供的Scala官网下载Scala编译器安装包 Windows系统环境安装Scala编译器 解压下载好的安装包

编写 unix和 windows的 Scala 脚本

编写 unix和 windows的 Scala 脚本 今天在看<Scala 编程>的时候看到附录了,里面提到了怎么在 unix 和 windows 下面编写 scala 脚本. 之前我也一直想用 scala 来在 unix 下写一些脚本,代替 shell,因为我对 shell 说实话不是很熟悉. 先直接给出一个可以正常的运行的例子把: #!/bin/sh exec scala "$0" "$@" !# 1.to(10).foreach(println)

io-dom4j中因为输出流未正确关闭,导致再次获取单例模式的document时,对象为null

问题描述 dom4j中因为输出流未正确关闭,导致再次获取单例模式的document时,对象为null 一:如下是获取单例模式的document对象. private static Document returndoc(Document docuname, String xmlname) { if (docuname != null) { return docuname; } SAXReader reader = new SAXReader(); // 如果不存在就创建对象. try { docu

scala中集合的交集、并集、差集

scala中有一些api设计的很人性化,集合的这几个操作是个代表: 交集: scala> Set(1,2,3) & Set(2,4) // &方法等同于interset方法 scala> Set(1,2,3) intersect Set(2,4) 并集: scala> Set(1,2,3) ++ Set(2,4) scala> Set(1,2,3) | Set(2,4) // |方法等同于union方法 scala> Set(1,2,3) union Set(

[设计模式实践之路](1)单例模式

[简介] 单例模式(Singleton)保证一个类仅有一个实例,并提供一个访问它的全局访问点.      实现单例模式的一个最好的方法就是让类自身负责保存它的唯一实例.这个类可以保证没有其他实例可以创建,并且它可以提供一个访问该实例的方法. [特点] 单例模式具有一下特点: 单例类只有一个实例 单例类必须自己创建自己的唯一实例 单例类必须给所有其他对象提供这一实例 [分类] 主要的就是懒汉单例,饿汉单例 [懒汉单例] package Mode; /** * Java设计模式之单例模式 * @au

scala dynamics 示例

简介     scala 新版本 2.10 引入了 Dynamic 这个 trait,意思上就是希望能够动态的 handle 一些东西 示例 package cn.cloud.scala import scala.language.dynamics import scala.collection.mutable.HashMap class DynamicPerson extends Dynamic { //定义一个方法类型 CallFun,它接收 Int 类型参数,并返回 String 类型 ,