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. ecshop首页调用指定分类的所有产品(指定一级调二级)

    第一种方法 第一 在/includes/lib_goods.php下增加如下代码,用过网上的直接换掉就可以 function index_get_cat_id_goods_best_list($cat ...

  2. CodeForces 343D 线段树维护dfs序

    给定一棵树,初始时树为空 操作1,往某个结点注水,那么该结点的子树都注满了水 操作2,将某个结点的水放空,那么该结点的父亲的水也就放空了 操作3,询问某个点是否有水 我们将树进行dfs, 生成in[u ...

  3. 【C语言的日常实践(十二)】命令行参数

    C计划main函数有两个参数.文章1一个通常被称为argc,它代表的命令行参数的个数. 第2个通常称为argv.它指向一组參数值. 指针数组:这个数组的每一个元素都是一个字符指针,数组的末尾是一个NU ...

  4. bestcoder44#1002

    这题采用分治的思想 首先,根据最后一位是否为1,将数分为两个集合,  集合与集合之间的lowbit为1, 然后将每个集合内的元素,倒数第二位是否为1,将数分为两个集合,集合与集合之间的lowbit为2 ...

  5. 点集配对问题(状态dp)

    给定n个点(n是偶数)使得两个点两两配对,最后总的距离和最小. 用是表示集合,那么dp[s]表示集合s配对后的最小距离和  , 状态转换方程为  表示集合中任意拿两个元素配对,然后转移为更小的两个集合 ...

  6. TP-LINK telnet远程 重启路由器(转)

    突然断网,以前房东的路由器管理页面可以打开,今天突然间就打不开了.ping了下,可以ping通,于是就想起了房东的路由器是TP-LINK的 可以 telnet登陆的.每次,断网,我都会重启房东的路由器 ...

  7. 【NOIP2002】矩形覆盖 DFS

    首先,我喜欢愤怒搜索,因为尽管说K<=4,的确K小于或等于3的. 当然某些K<=3还600ms的我就不加评论了. 好吧,可是怎么搜呢?我们考虑到矩形数量非常少,所以能够怒搜矩形. 一些神做 ...

  8. muduo网络图书馆评测

    上个月看到朋友推荐mudo网络图书馆,该代码是在国内同行中,开源工程后.甚至钦佩.根据mudo手动和035代码的版本看起来正在建设中.感觉是一个比较成熟且易于使用的网络库.我的手也有自己的网络库,虽然 ...

  9. Android:刚6瓶啤酒4两56度白酒下肚,竟然20分钟做了一手机版站点 !

    刚6瓶啤酒4两56度白酒下肚,竟然20分钟不到时间做了一手机版站点 !人有多大潜力你知道吗? 大家有兴趣的能够用手机或微信打开 http://xh.yunxunmi.com/  看看俺这酒后之做! 很 ...

  10. view和activity的区别(转)

    activity相当于控制部分,view相当于显示部分.两者之间是多对多的关系,所有东西必须用view来显示. viewGroup继承自view,实现了ViewManager,ViewParent接口 ...