JAVA设计模式--辛格尔顿
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三大基本特性 封装 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的属性和方法只让可信的类操作,对不可信的进行信息隐藏. 继承 继承是指这样一种能力,它可以使 ...
随机推荐
- Date和String类型的相互转换
String转Date: SimpleDateFormat bartDateFormat = new SimpleDateFormat("MM-dd-yyyy"); String ...
- 2012Android开发热门资料(110个)
下载中心完整附件下载地址:http://down.51cto.com/data/412494 附件内容部分预览: 专题推荐: Android控:平板电脑HD精品游戏软件合集(共32个) http:// ...
- 采用Bash脚本性能监控过程
为一个Linux过程监控,采用Bash脚本. 采用ps命令的过程监控,使用周期加上连续监测的睡眠时间. 使用方法: psmonitor.sh -p [pid] -d [interval] -n [st ...
- ipconfig /flushdns 清除系统DNS缓存
1.ipconfig /flushdns的作用 ipconfig /flushdns 这是清除DNS缓存用的. 当訪问一个站点时系统将从DNS缓存中读取该域名所相应的IP地址,当查找不到时就会到系统中 ...
- Android SDK 5.0 这个语句带来折腾 - 生命在于折腾!
Android SDK 5.0 带来的这番折腾 - 生命在于折腾! 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一 ...
- contextmenu
void Loaded(object sender, RoutedEventArgs e) { ContextMenu contextMenu = new ContextMenu(); context ...
- Facebook Asynchronous Layout and Rending
Facebook Asynchronous Layout and Rending by 吴雪莹 dispatch_async(backgroundQueue, ^{ storyNode = [[FBS ...
- LinearLayout具体解释一:LinearLayout的简单介绍
LinearLayout,中文意思是线性布局.假设你是初学android的,肯定会非常困惑"啥叫布局",啥又叫"线性布局"呢. 有的时候,我尝试用官方的语言去解 ...
- AWR报告生成
ORACLE数据库两个比較重要的问题查看报告:awrrpt.sql,ashrpt.sql 生成报告的脚本一般存放在例如以下路径: /home/TEST/db/tech_st/11.2.0/rdbms/ ...
- 【JUnit4.10来源分析】6 Runner
org.junit.runner.Runner它是JUnit作业引擎.它在许多类型的支持下的.处理试验和生产(Description).Failure和Result和其它输出. Runner参见图主类 ...