设计模式之单例模式(三种实现方式)

一、单例模式要点

1.单例,顾名思义,某个类仅仅能有一个实例。

2.它必须自行创建这个唯一的实例。

3.它必须自行向整个系统提供这个实例。

二、单例模式的三种实现

1.饿汉式单例类(类载入时就初始化)

代码实现

public class EagerSingleton {
    //私有的类成员常量
    private static final EagerSingleton SINGLETON=new EagerSingleton();
    //私有的默认构造方法。此类不能被继承
    private EagerSingleton(){}
    //静态工厂方法
    public static EagerSingleton getInstance(){
        return SINGLETON;
    }  

}  

Java语言中的单例类的一个最重要的特点是类的构造方法是私有的。从而避免外界利用构造方法直接创建出人意多飞实例。

2.懒汉式单例类(第一次调用才初始化。延迟)

代码实现

public class LazySingleton {
private  static LazySingleton singleton=null;
//私有的默认构造方法,此类不能被继承
private LazySingleton(){}
//同步。静态工厂方法,返回此类的唯一实例
public synchronized static LazySingleton getInstance(){
    if(singleton==null){
        singleton=new LazySingleton();
    }
    return singleton;
}  

在懒汉式单例中,假设在多线程中訪问会出现线程安全问题,easy造成多个实例对象产生,因此对懒汉式单例须要进一步加强,代码例如以下:

public class DoubleCheckSingleton {
    private volatile static DoubleCheckSingleton singleton = null;  

    // 私有的默认构造方法,此类不能被继承
    private DoubleCheckSingleton() {
    }  

    // 静态工厂方法,返回此类的唯一实例
    public static DoubleCheckSingleton getInstance() {
        if (singleton == null) {
            synchronized (DoubleCheckSingleton.class) {
                if (singleton == null) {
                    singleton = new DoubleCheckSingleton();
                }
            }
        }
        return singleton;
    }  

}  

3.登记式单例类

登记式单例类是为了克服饿汉式单例类和懒汉式单例类不可继承的缺点而设计的。

 package com.zzs.singleton;  

import java.util.HashMap;  

public class RegSingleton {
    private static HashMap registry=new HashMap();
    /**静态代码块
        *静态代码块优先于主方法运行,而在类中定义的静态代码会优先于构造块运行,并且无论产生多少对象。静态代码块仅仅运行一次。
        */
    static{
        RegSingleton singleton=new RegSingleton();
        registry.put(singleton.getClass().getName(), singleton);
    }  

    protected RegSingleton(){}  

    public static RegSingleton getInstance(String name){
        if(name==null){
            name="com.zzs.singleton.RegSingleton";
        }
        if(registry.get(name)==null){
            try {
                registry.put(name, Class.forName(name).newInstance());
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return (RegSingleton) registry.get(name);
    }  

}  
package com.zzs.singleton;  

public class RegSingletonChild extends RegSingleton {
    //因为子类必须同意父类以构造方法调用产生实例,所以它的构造方法必须是公开的。protected或public
    protected RegSingletonChild() {
    }
    //静态方法工厂
    public static RegSingletonChild getInstance() {
        return (RegSingletonChild) RegSingleton
                .getInstance("com.zzs.singleton.RegSingletonChild");
    }
}  

三、在什么情况下使用单例模式

使用单例模式的一个必要条件:在一个系统中要求仅仅有一个类的实例时应当使用单例模式。反过来说,假设一个类能够有几个实例共存,那么就没有必要使用单例类。java语言中的Runtime对象就是一个单例模式。

时间: 2024-10-23 01:19:41

设计模式之单例模式(三种实现方式)的相关文章

单例模式的三种实现方式

一.单例模式的三种实现方式 1. 什么是单例模式 基于某种方法,实例化多次,得到同一个实例/对象 2. 为什么用单例模式 实例化多次,得到的对象属性内容都一样时,应该将这些对象指向同一个内存,即同一个实例,来节省内存空间 1. 实现单例模式方式一:类内部定义类方法实现 实现方法:类中定义了一个类方法 # 未单例模式前 import setting class Mysql: def __init__(self,ip,port): self.ip=ip self.port=port @classme

spring注解之@Import注解的三种使用方式

目录 1.@Import注解须知 2.@Import的三种用法 3.@Import注解的三种使用方式总结 @ 1.@Import注解须知 1.@Import只能用在类上 ,@Import通过快速导入的方式实现把实例加入spring的IOC容器中 ? 2.加入IOC容器的方式有很多种,@Import注解就相对很牛皮了,@Import注解可以用于导入第三方包 ,当然@Bean注解也可以,但是@Import注解快速导入的方式更加便捷 ? 3.@Import注解有三种用法 2.@Import的三种用法

CSS的三种定位方式介绍(转载)

在CSS中一共有N种定位方式,其中,static ,relative,absolute三种方式是最基本最常用的三种定位方式.他们的基 本介绍如下. static默认定位方式relative相对定位,相对于原来的位置,但是原来的位置仍然保留absolute定位,相对于最近的非标准刘定位,原来的位置消失,被后边的位置所顶替 下面先演示相对定位的案例 [html] view plain copyprint? <!DOCTYPE html> <html> <head> <

MyEclipse中web服务器的三种配置方式

初学Javaweb开发的人们都会遇到一个问题,就是服务器环境的搭建配置问题.下面介绍三种服务器的搭建方式. 直接修改server.xml文件 当你写了一个web应用程序(jsp/servlet),想通过浏览器直接去访问这个页面,需要在Tomcat中配置相关路径: 找到Tomcat下conf目录,你会看到有个server.xml,即服务器配置文件.用文本编译器打开,拉到Host标签,在它结束前加上我们的应用程序路径: <Context path="/HelloWeb" docBas

1、打印二进制机器码,程序内存分析,大端序小端序,指针数组,数组指针,数组的三种访问方式,typedef,#if-0-#endif,求数组大小,括号表达式

 1.打印二进制机器码(分别表示32位的和64位的) #include <stdio.h> /*按照8位的长度打印一个数值*/ void dis8bit(char val) { int bit = 8; while(bit--) { if(1<<bit&val){ printf("1"); } else { printf("0"); } if(!(bit%4)) printf(" "); } putchar(1

SQL Server 中的三种分页方式

USE tempdb GO SET NOCOUNT ON --创建表结构 IF OBJECT_ID(N'ClassB', N'U') IS NOT NULL DROP TABLE ClassB GO CREATE TABLE ClassB(ID INT PRIMARY KEY, Name VARCHAR(16), CreateDate DATETIME, AID INT, Status INT) CREATE INDEX IDX_CreateDate ON ClassB(CreateDate)

支付宝5月4日起将停止收款主页业务 保留三种收款方式

4月28日消息,支付宝近日发布公告称,将于5月4日起停止收款主页业务(产品功能将无法使用),但并未公布停止业务的具体信息. 据了解,收款主页业务是用户可以自己制作一个支付宝账号的链接,把这个链接发给付款人后,对方就可以输入金额给该用户付款. 支付宝收款主页截图 支付宝公告称,收款主页业务停止之后,用户可以有三种方式进行收款:生成专属支付宝收款账户码,将账户二维码图片分享出去:在电脑上使用我要收款:在手机上,使用支付宝钱包的我要收款. 以下为公告原文: 鉴于收款主页(https://me.alip

Hibernate的Api以及三种查询方式

Hibernate  Api |-- Configuration       配置管理类对象 config.configure();    加载主配置文件的方法(hibernate.cfg.xml) 默认加载src/hibernate.cfg.xml config.configure("cn/config/hibernate.cfg.xml");   加载指定路径下指定名称的主配置文件 config.buildSessionFactory();   创建session的工厂对象 |--

使用JavaScript判断图片是否加载完成的三种实现方式

有时需要获取图片的尺寸,这需要在图片加载完成以后才可以.有三种方式实现,下面一一介绍. 一.load事件 <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>img - load event</title> </head> <body> <img id="img1" src="http:/

数组的三种定义方式

// 数组的三种定义方式 var arr = ['zhangsan','lisi','wangwu']; var arr1 = new Array('zhangsan','lisi','wangwu'); var arr2 = new Array(3); arr2[0] = 'zhangsan'; //注意:下标一定要写,不像在php中,下标是可以不写,是一直追加 // console.log(arr2); // 说明:js中,没有关联数组一说,数组下标都是数字 // 如果一个数组的下标是自定义