Singleton模式可以作为一种编程技术,让我们先从理论上说代码

单例模式三个关键点:

1)、某个类仅仅能有一个实例

2)、该类必须自行创建这个实例

3)、该类必须自行向整个系统提供这个实例

应用场景:

1)、window的任务管理器就是非常典型的单例模式,你肯定不能同一时候打开两个任务管理器

2)、数据库连接池技术一般採用的都是单例模式。由于数据库连接是一种数据库资源。系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的

效率损耗。这样的效率上的损耗还是很昂贵的,用单例模式来维护。就能够大大减少这样的损耗。

3)、我们在进行开发时对于配置文件的读取一般也是採用单例模式,由于配置文件里的内容是全局共享的资源。

4)、多线程的线程池设计一般也要考虑单例模式。线程池能方便对池中线程的控制。

5)、站点的统计类信息。一般也是採用单例模式,否则难以同步控制。比如统计我的博客的訪问量。

6)、我们开发应用程序的日志功能也是採用的单例模式,由于我们仅仅能有一个实例去追加日志信息,否则不好控制。

单例模式的几类写法:

1)饿汉式模式

怎么理解呢,饿了吗。所以我们做饭要很着急,这里也就是说。当类被载入的时候该类就已经将自己的实例创建出来了。

这也是空间换取时间的典型应用,怎么说呢? 我们在类载入的时候就实例化了这个对象。占用了内存空间,可是我们在用到这个对象的时候就不用去实例化了,

直接拿去用就能够了。也就节省可时间,这也就是空间换取时间。

ps:记得第一份工作(还在大三的时候)面试的时候面试官就让我举出我做过的项目中时间换取空间和空间换取时间的典型应用,给我问懵了。

代码:

package chc.singleton;
/**
* 饿汉式单例模式类
* @author haicheng.cao
* @time 2014.09.02 22:40
*/
public class EagerSingleton {
//类载入的时候就创建了自身的实例对象--饿汉式(空间换取时间)
public static EagerSingleton eagerSingleton=new EagerSingleton(); /**
* 显示的私有构造方法,防止其它类创建本类实例
*/
private EagerSingleton(){ } /**
* 静态工厂方法,其它类通过调用该方法来获取本类的实例对象
*/
public static EagerSingleton getEagerSingleton(){
return eagerSingleton;
}
}

2)懒汉式模式

这个怎么理解呢?懒人吗,举个样例。一个人立即要去面试的时候才開始写简历,就是说对象实例要用的时候才去创建。在这里也就是说在类载入的时候并没有创

建本类的实例对象,而是在其它类在第一次调用的时候才去创建。

这也是典型的时间换取空间的应用,就是嘛,类载入的时候没有创建对象。节省了内存。也就是节省了空间,调用的时候须要推断一下这个类的实例对象是否存

在,浪费了时间,这也就是时间换取空间。

代码:

package chc.singleton;
/**
* 懒汉式单例模式类
* @author haicheng.cao
* @time 2014.09.02 23:05
*/
public class LazySingleton {
//类载入的时候并没有创建自身实例化对象
public static LazySingleton lazySingleton=null; /**
* 显示的私有构造方法。防止其它类创建本类实例
*/
private LazySingleton(){ } /**
* 静态工厂方法,其它类通过调用该方法来获取本类的实例对象
*/
public static synchronized LazySingleton getLazySingleton(){
//第一次被调用的时候创建自身实例对象
if(lazySingleton==null){
lazySingleton=new LazySingleton();
}
return lazySingleton;
}
}
注意:我们给getEasySingleton()方法加了同步keyword,能够保证线程安全。可是这样做比較影响程序的性能,我们能不能改善一下呢?看以下的:

3)双重检查加锁

双重检查加锁机制的意思就是:我们在调用getEasySingleton()方法的时候不同步,进入方法内我们推断一下实例对象是否存在。假设不存在我们在进入同步代

码块。这是第一重检查,进入同步块后再进行推断,推断实例是否存在,假设不存在再创建这个对象的实例。这就是第二重检查。

这样。就仅仅有第一次调用的时候

运行了一次同步代码块,其余的时候就不须要同步了,提升了程序的性能。

代码:

package chc.singleton;
/**
* 双重检查加锁。针对懒汉式提升性能
* @author haicheng.cao
* @time 2014.09.02 22:40
*/
public class TwoCheck {
private volatile static TwoCheck twoCheck = null; private TwoCheck(){ } public static TwoCheck getInstance(){
//先检查实例是否存在,假设不存在才进入以下的同步块
if(twoCheck == null){
//同步块,线程安全的创建实例
synchronized (TwoCheck.class) {
//再次检查实例是否存在,假设不存在才真正的创建实例
if(twoCheck == null){
twoCheck = new TwoCheck();
}
}
}
return twoCheck;
}
}

-------------------------------------以下续写与2014.09.03 21:15-----------------------------------------------------

昨天在写这个东西的时候一直在纠结一个问题,如果有一部分全局共享的变量,我们能够通过在类中声明静态属性。然后通过静态方法来初始化声明的那些属性。

然后这些静态的变量在不论什么一个类中都能够被调用了。就像以下这种代码:

package chc.statics;
public class StaticDemo {
public String logPath=null; public void init(){
logPath="c://log.txt";
}
}

这种代码不是全然能够替代单例的功能吗?

今天上班问了下领导。给我解释的非常清楚,类中声明静态变量的方式的确能够实现单例模式的功能。可是,上面代码那种方式你须要在项目启动的时候调用一下

StaticDemo类的init()方法。单例模式就是全然由自身去维护自己,不须要借助外力。

另一种情况:就是当有些全局属性是动态变化的时候,那么对于静态变量的方式就须要程序不断的去操作该类的动态属性,而静态类能够灵活的自己控制。解除

了代码的耦合。

package chc.singleton;
import java.io.*;
public class Singleton {
public static File file=null; public static long lastModified;
private static Singleton s=null; private Singleton(){
lastModified=file.lastModified();
}
public synchronized static Singleton getSingleton() {
//假设变量lastModified的值与文件最后一次被改动的时间值不同的话,又一次实例化一下
if(s==null && lastModified!=file.lastModified() ){
s=new Singleton();
}
return s;
}
}

这个样例就非常直观了。类中的lastModified的值是动态的,假设用静态代码块去维护的话。程序在每一次改动这个文件的时候都要调用一次静态代码

块又一次初始化一下这个变量,单例中却能够自己灵活的进行维护,不须要别的类辅助。

-------------------------------------以下续写与2014.11.03 20:40-----------------------------------------------------

饿汉式存在着占用资源的问题。懒汉式存在着线程安全的问题,以下看一个巧妙的写法,将懒汉式与饿汉式的长处集成在了一起。攻克了懒汉式与饿汉式的弊端。

package hirain;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* 即实现了延迟载入,又线程安全
* @author haicheng.cao
*/
public class AppConfig5 { //静态内部类在第一次使用的时候被装载
private static class AppConfig5Holder{
private static AppConfig5 instance = new AppConfig5();
}
/**
* 定义一个方法来为client提供AppConfig类的实例
* @return 一个AppConfig的实例
*/
public static AppConfig5 getInstance(){
return AppConfig5Holder.instance;
}
/**
* 私有化构造方法
*/
private AppConfig5(){
//调用读取配置文件的方法
readConfig();
} private String id; private String name; public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} /**
* 读取配置文件,把配置文件里的内容读出来设置到属性上
*/
private void readConfig(){
Properties p = new Properties();
InputStream in = null;
try {
in = new BufferedInputStream (new FileInputStream("AppConfig.properties"));
p.load(in);
//把配置文件里的内容读出来设置到属性上
this.id = p.getProperty("id");
this.name = p.getProperty("name");
} catch (IOException e) {
System.out.println("装载配置文件出错了,详细堆栈信息例如以下:");
e.printStackTrace();
}finally{
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} }

关键点:静态内部类的使用,静态内部类的静态变量仅仅有在静态内部类被使用的时候才会载入中。

版权声明:本文博主原创文章,博客,未经同意不得转载。

JAVA设计模式--辛格尔顿的更多相关文章

  1. java设计模式- (1)单例模式

    参加校园招聘的笔试,发现公司都会考一些java设计模式,所以上网查询相关内容,总结常用的几种单例模式. 单例模式(Singleton Pattern)是 Java中最简单的设计模式之一.这种类型的设计 ...

  2. JAVA 设计模式 桥接模式

    用途 桥接模式 (Bridge) 将抽象部分与实现部分分离,使它们都可以独立的变化. 桥接模式是一种结构式模式. 结构

  3. java设计模式 策略模式Strategy

    本章讲述java设计模式中,策略模式相关的知识点. 1.策略模式定义 策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户.策略模式属于对象的 ...

  4. Java设计模式之行为型模式

    行为型模式共11种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 策略模式:策略模式的决定权在用户,系统本身提供不同 ...

  5. Java设计模式(三) 抽象工厂模式

    原创文章,同步发自作者个人博客,转载请注明出处 http://www.jasongj.com/design_pattern/abstract_factory/ 抽象工厂模式解决的问题 上文<工厂 ...

  6. Java设计模式(十二) 策略模式

    原创文章,同步发自作者个人博客,http://www.jasongj.com/design_pattern/strategy/ 策略模式介绍 策略模式定义 策略模式(Strategy Pattern) ...

  7. Java设计模式(二) 工厂方法模式

    本文介绍了工厂方法模式的概念,优缺点,实现方式,UML类图,并介绍了工厂方法(未)遵循的OOP原则 原创文章.同步自作者个人博客 http://www.jasongj.com/design_patte ...

  8. Java设计模式(一) 简单工厂模式不简单

    摘要:本文介绍了简单工厂模式的概念,优缺点,实现方式,以及结合Annotation和反射的改良方案(让简单工厂模式不简单).同时介绍了简单工厂模式(未)遵循的OOP原则.最后给出了简单工厂模式在JDB ...

  9. Java设计模式(十三) 别人再问你设计模式,叫他看这篇文章

    原创文章,转载请务注明出处 OOP三大基本特性 封装 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的属性和方法只让可信的类操作,对不可信的进行信息隐藏. 继承 继承是指这样一种能力,它可以使 ...

随机推荐

  1. 使用OGG&quot;Loading data from file to Replicat&quot;的方法应该注意的问题:replicat进程是前台进程

    使用OGG的 "Loading data from file to Replicat"的方法应该注意的问题:replicat进程是前台进程 因此.最好是在vncserver中调用该 ...

  2. java-IO操作性能对照

    在软件系统中.IO速度比内存速度慢,IO读写在非常多情况下会是系统的瓶颈. 在java标准IO操作中,InputStream和OutputStream提供基于流的IO操作.以字节为处理单位:Reade ...

  3. 最简单的Java框架

    框架framework的目的是定义骨架式方案,处理各种相同的底层细节:而开发人员使用框架时,能够依照自己的需求实现自己的功能--仅仅须要填入自己的东西/flesh. 最简单的框架,类似于JUnit,它 ...

  4. ECshop lib_base.php on line 1241 错误解决方法

    ECSHOP做的一个网站,突然报这个错误,整个网站打不开,后来找了很久,终于找到这个方法,亲测可用 Notice: Undefinedvariable: data in D:\wwwroot\KISS ...

  5. C陷阱与缺陷之语法陷阱

    2.1理解函数声明 不论什么C变量的声明都由两部分组成:类型以及一组类似表达式的声明符号.比如 float f; 这个声明的含义是:当对其求值时,表达式f和g的类型为浮点数类.由于声 明符与表达式的相 ...

  6. ZOJ 3795 Grouping 求最长链序列露点拓扑

    意甲冠军:特定n积分.m向边条. 该点被划分成多个集合随机的每个集合,使得2问题的关键是无法访问(集合只能容纳一个点) 问至少需要被分成几个集合. 假设没有戒指,接着这个话题正在寻求产业链最长的一个有 ...

  7. windows下cocos2dx3.0开发环境及Android编译环境搭建

    cocos2dx更新到了3.x版本号,自己一直没有换,如今开发组要求统一换版本号,我就把搭建好开发环境的过程记录下来. 一.Windowns下开发环境搭建 1.  所需工具         1)coc ...

  8. Mono+CentOS+Jexus

    在.NET Core之前,实现.Net跨平台之Mono+CentOS+Jexus初体验准备工作 本篇文章采用Mono+CentOS+Jexus的方式实现部署.Net的Web应用程序(实战,上线项目). ...

  9. firefox os 2.0版模拟器QQ初体验

    供firefox os 爱侣.firefox os 手机迟迟没有感到些许遗憾在中国上市会,但是,我们必须相信firefox os 登陆中国是迟早的事,腾讯QQ已经登陆firefox os 应用市场,今 ...

  10. 高级项目 它 集群环境建设(两)MySQL簇

    最后博文我们介绍一下相关概念集群,今天我们要介绍的博文MySQL相关内容集群. 1.MySQL集群简单介绍 MySQL群集技术在分布式系统中为MySQL数据提供了冗余特性,增强了安全性,使得单个MyS ...