参看了crazybob的关于单态模式的文章http://crazybob.org/2007/01/lazy-loading-singletons.html,非常受益。最近在学习设计模式,有必要整理下singletion的几种实现方式:
简单说来,大体是有三种实现方式:
1、饿汉式 在下面这个例子中,这个类被加载时,静态变量m_instance 会被初始化,此时类的私有构造子会被调用。这时候,单例类的惟一实例就被创建出来了。
//饿汉式:
public class EagerSingleton {
/** @label Creates */
private static final EagerSingleton m_instance = new EagerSingleton();
/**
* 私有的默认构造函数
*/
private EagerSingleton() { }
/**
* 静态工厂方法
*/
public static EagerSingleton getInstance() {
return m_instance;
}
}
2、懒汉式
Java代码
//懒汉式
//使用到才实例化 不使用不实例化,比如你使用此类的其他静态方法 而饿汉式只要用到就被实例化
public class LazySingleton
{
private LazySingleton() { }
//对静态工厂方法使用了同步化,以处理多线程环境
public synchronized static LazySingleton getInstance()
{
if (m_instance == null)
{
m_instance = new LazySingleton();
}
return m_instance;
}
}
注:(1)、从资源利用效率角度来讲,饿汉式比懒汉式单例类稍差些。
(2)、从速度和反应时间角度来讲,饿汉式比懒汉式单例类稍好些。
3、登记式
Java代码
//登记式:
import java.util.HashMap;
public class RegSingleton
{
static private HashMap m_registry = new HashMap();
static
{
RegSingleton x = new RegSingleton();
m_registry.put( x.getClass().getName() , x);
}
/**
* 保护的默认构造子
*/
protected RegSingleton() {}
/**
* 静态工厂方法,返还此类惟一的实例
*/
static public RegSingleton getInstance(String name)
{
if (name == null)
{
name = "com.javapatterns.singleton.demos.RegSingleton";
}
if (m_registry.get(name) == null)
{
try
{
m_registry.put( name,Class.forName(name).newInstance() ) ;
}
catch(Exception e)
{
System.out.println("Error happened.");
}
}
return (RegSingleton) (m_registry.get(name) );
}
/**
* 一个示意性的商业方法
*/
public String about()
{
return "Hello, I am RegSingleton.";
}
}
它的子类RegSingletonChild 需要父类的帮助才能实例化。
Java代码
import java.util.HashMap;
public class RegSingletonChild extends RegSingleton
{
public RegSingletonChild() {}
/**
* 静态工厂方法
*/
static public RegSingletonChild getInstance()
{
return (RegSingletonChild)
RegSingleton.getInstance( "com.javapatterns.singleton.demos.RegSingletonChild" );
}
/**
* 一个示意性的商业方法
*/
public String about()
{
return "Hello, I am RegSingletonChild.";
}
}
缺点:
1、RegSingletonChild类的构造函数是public,就等于允许了以这样方式产生实例而不在父类的登记中。
2、GoF 曾指出,由于父类的实例必须存在才可能有子类的实例,这在有些情况下是一个浪费。
下面我们接着补充:
我们使用的多为前两种方式:饿汉式和懒汉式。究竟选择哪一个,我们这里有一个原则。在系统上线使用时,你一般都需要一次性加载所有的单态,以便于尽早发现可能出现的问题;而在开发和测试阶段,你只是需要加载那些必须的单态而不会浪费时间。
针对懒汉式(用到时加载),我们进一步拓展开来:上面给的代码实现方式,是使用原始的老的线程同步机制,以保证线程安全。
在java 1.5 之后,出现了volatile 关键字,此关键字能保证其修饰的变量不允许有不同于“主”内存区域(Java有个思想叫“主”内存区域,这里存放了变量目前的“准确值”。每个线程可以有它自己的变量拷贝,而这个变量拷贝值可以和“主”内存区域里存放的不同。因此实际上存在一种可能:“主”内存区域里的i1值是1,线程1里的i1值是2,线程2里的i1值是3)的变量拷贝,换句话说,一个变量经volatile修饰后在所有线程中必须是同步的;任何线程中改变了它的值,所有其他线程立即获取到了相同的值。
接着就有了基于Double-Checked Locking(DCL)的懒汉式,这种方式通过“主”内存区对volatile修饰的变量域进行检查,并且在必要的时候进行加锁。
public class Singleton {
private volatile Singleton instance;
private Singleton(){}
public Singleton getInstance(){
if(null == instance){
synchronized (Singleton.class) {
if(null == instance)
instance = new Singleton();
}
}
return instance;
}
}
但DCL方式的懒汉,使用并不广泛,因为相比较传统的方法加锁机制,DCL方式并不快多少。所以大多数人仍在使用传统的方式。
但现在有一种懒汉方式,非常的流行,采取的是Initialization on Demand Holder(IODH),此方式代码量不多,并且线程同步问题解决的非常完美。代码如下:
public class Singleton {
private static class SingletonHolder{
private static Singleton instance = new Singleton();
}
private Singleton(){}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
单例模式,先学到这里。还有巨多的模式等着我呢,慢慢来。。。
分享到:
相关推荐
单态模式(Singleton Pattern)是软件设计模式中的一种,它保证了类只有一个实例,并提供一个全局访问点。这种模式在很多场景下非常有用,比如配置管理、线程池、缓存管理和日志记录等,因为它可以确保在整个系统中...
单态模式的定义: Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。 在项目的很多地方都会用到它,比如说数据库的链接。 使用Singleton的好处还在于可以节省内存,因为它限制了实例...
在提供的代码示例中,展示的是饿汉式的单态模式实现。具体如下: ```java package org.singleton; // 单态设计模式 class Singleton3 { // 私有构造函数防止外部直接实例化 private Singleton3() {} // 静态...
### 单态模式的实现方式 #### 1. 饿汉式(静态初始化) ```java public class Singleton { // 在类加载时初始化实例,保证多线程环境下的安全性 private static Singleton instance = new Singleton(); ...
单态模式(Singleton Pattern)是软件设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。在.NET环境中,无论是C#还是ASP.NET项目,单态模式都是经常被用到的设计模式之一,尤其在处理全局配置、...
下面将详细阐述单态模式的原理、实现方式以及它在三层架构中的应用。 首先,理解单态模式的基本结构。单态模式包含一个私有的构造函数,以防止外部直接创建实例,同时提供一个静态方法或属性来获取这个唯一的实例。...
二、单态模式的实现方式 1. 饿汉式(Eager Initialization):在类加载时就初始化,所以是线程安全的。代码如下: ```java public class Singleton { private static final Singleton INSTANCE = new Singleton(); ...
总的来说,单态模式是一种强大的设计模式,但使用时应权衡其优缺点,并根据具体应用场景选择合适的实现方式。在某些情况下,如依赖注入框架或使用枚举类型替代,可以避免单态模式带来的复杂性。
2. **MFC中的单态模式实现** 在MFC中,通常使用`CWinApp`类作为应用程序的单例,因为每个MFC程序只有一个`CWinApp`实例。不过,我们也可以为自定义类实现单例模式。以下是一种常见的实现方式: - **私有化构造...
实现单态模式主要有两种方式:饿汉式和懒汉式。 1. 饿汉式(Eager Initialization): 饿汉式是在类加载时就完成了实例化,避免了线程同步问题。因为实例在类加载时就创建,所以是线程安全的。代码通常如下: ``...
单态模式(Singleton Pattern)和简单工厂模式(Simple Factory Pattern)是软件设计中常见的两种创建型设计模式。在Java编程中,它们都是为了简化对象的创建过程,但各自有着不同的应用场景和特点。 单态模式是一...
以下是两种常见的单态模式实现方式: 1. 饿汉式(Eager Initialization): 这种方式在类加载时就完成了初始化,所以类加载比较慢,但获取实例的速度快,且线程安全。如: ```java public class Singleton { ...
**单态模式(Singleton Pattern)** 单态模式是一种创建型设计模式,其核心在于保证一个类只有一个实例,并提供一个全局访问点。这种模式的主要目的是为了节约系统资源,避免频繁地创建和销毁对象,同时提供了一个...
DataSource的单态模式(SingleTon)程序---马克-to-win java视频 数据源 单态模式 dataSource Singleton
通过上述的教学过程设计,学生不仅能够理解单态设计模式的基本原理,还能了解到其实现的具体步骤及其在实际项目中的应用场景。更重要的是,这种方法能够帮助学生建立起面向对象编程的思想,为他们未来的学习和发展...
在C++中实现单态模式,通常有几种常见的方式: 1. **懒汉式(Lazy Initialization)**: 这种方式延迟到第一次使用时才创建单例对象。为了确保线程安全,通常会使用`std::call_once`或者`std::mutex`来控制初始化...
单态模式 马克-to-win Java视频 Singleton 单例模式
单态模式 马克-to-win java视频 Singleton 单例模式
单态模式 马克-to-win java视频 Singleton 单例模式
1. **单态模式实现**: - 在Java中,我们通常通过私有构造函数和一个静态方法来创建并返回单例对象。以下是一个简单的单例模式实现: ```java public class SingletonLogin { private static SingletonLogin ...