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;
}
}
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设计模式--辛格尔顿的更多相关文章
-
java设计模式- (1)单例模式
参加校园招聘的笔试,发现公司都会考一些java设计模式,所以上网查询相关内容,总结常用的几种单例模式. 单例模式(Singleton Pattern)是 Java中最简单的设计模式之一.这种类型的设计 ...
-
JAVA 设计模式 桥接模式
用途 桥接模式 (Bridge) 将抽象部分与实现部分分离,使它们都可以独立的变化. 桥接模式是一种结构式模式. 结构
-
java设计模式 策略模式Strategy
本章讲述java设计模式中,策略模式相关的知识点. 1.策略模式定义 策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户.策略模式属于对象的 ...
-
Java设计模式之行为型模式
行为型模式共11种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 策略模式:策略模式的决定权在用户,系统本身提供不同 ...
-
Java设计模式(三) 抽象工厂模式
原创文章,同步发自作者个人博客,转载请注明出处 http://www.jasongj.com/design_pattern/abstract_factory/ 抽象工厂模式解决的问题 上文<工厂 ...
-
Java设计模式(十二) 策略模式
原创文章,同步发自作者个人博客,http://www.jasongj.com/design_pattern/strategy/ 策略模式介绍 策略模式定义 策略模式(Strategy Pattern) ...
-
Java设计模式(二) 工厂方法模式
本文介绍了工厂方法模式的概念,优缺点,实现方式,UML类图,并介绍了工厂方法(未)遵循的OOP原则 原创文章.同步自作者个人博客 http://www.jasongj.com/design_patte ...
-
Java设计模式(一) 简单工厂模式不简单
摘要:本文介绍了简单工厂模式的概念,优缺点,实现方式,以及结合Annotation和反射的改良方案(让简单工厂模式不简单).同时介绍了简单工厂模式(未)遵循的OOP原则.最后给出了简单工厂模式在JDB ...
-
Java设计模式(十三) 别人再问你设计模式,叫他看这篇文章
原创文章,转载请务注明出处 OOP三大基本特性 封装 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的属性和方法只让可信的类操作,对不可信的进行信息隐藏. 继承 继承是指这样一种能力,它可以使 ...
随机推荐
-
SQLSERVER全文搜索
SQLSERVER全文搜索 看这篇文章之前请先看一下下面我摘抄的全文搜索的MSDN资料,基本上MSDN上关于全文搜索的资料的我都copy下来了 并且非常认真地阅读和试验了一次,并且补充了一些SQL语句 ...
-
SQL语句查询某表的所有字段及数据类型
SQL语句查询某表的所有字段及数据类型 SELECT name AS column_name , TYPE_NAME(system_type_id) AS column_type , max_leng ...
-
[原创]java WEB学习笔记50:文件上传案例
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
-
easyui-datagrid分页查询
不想写语言描述了,直接代码吧! js: $(document).ready(function () { var driver_datagrid; $('#job').combobox({ url: ' ...
-
sizeof和strlen的区别和联系总结
link:http://blog.csdn.net/ghevinn/article/details/9974967 strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头 ...
-
VUE2.0实现购物车和地址选配功能学习第七节
第七节 卡片选中,设置默认 1.卡片选中html:<li v-for="(item,index) in filterAddress" v-bind:class="{ ...
-
分布式系统监视zabbix讲解四之可视化--技术流ken
图形 概述 随着大量的监控数据被采集到Zabbix中,如果用户可以以可视化的表现形式来查看发生了什么事情,那么和仅仅只有数字的表现形式比起来则更加轻松. 以下是进行图形设置的地方.图形可以一目了然地掌 ...
-
按科室统计 2.181222版本 关联查询join 不对
SQL: select t0.deptName, t0.deptId, t0.startTime, t0.endTime, IFNULL(t0.num,) as num0, IFNULL(t1.num ...
-
序列化与Json
序列化: 将数据结构或对象转换成二进制串的过程. 反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程. 首先我们通过复制文件举例,这里面就包含序列化与反序列化的过程: public ...
-
C#提高------------------------Attribute自定制概念
C#基础知识梳理系列八:定制特性Attribute 摘 要 设计类型的时候可以使用各种成员来描述该类型的信息,但有时候我们可能不太愿意将一些附加信息放到类的内部,因为这样,可能会给类型本身的信息描 ...