使用Java语言编写设计模式-4.创建型模式-单例模式
原创2022年9月8日大约 8 分钟约 2351 字
4.创建型模式-单例模式
4.1.章节内容概述
本章节涉及主要内容有:
4.1.章节内容概述
4.2.章节内容大纲
4.3.简介
4.4.应用场景
4.5.优缺点
4.6.角色及其职责
4.7.模型
4.8.示例
4.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。
4.2.章节内容大纲
4.3.简介
单例模式(Singleton Pattern)是一种创建型设计模式,又名单件模式或单态模式,目的是为了保证一个类只有一个实例对象,并提供一个获取该实例对象的全局方法,通过这个全局方法创建的所有实例对象都是同一个实例对象,这个类称为单例类。单例模式的要点有三个:一是某个类只能有一个实例对象;二是这个类必须自行创建这个实例对象;三是这个类必须自行向整个系统提供这个实例。
4.4.应用场景
单例模式应用的场景一般发现在以下条件下
资源共享的情况下: 避免由于资源操作时导致的性能或损耗等
控制资源的情况下: 方便资源之间的互相通信
具体应用场景
a.Windows的Task Manager(任务管理器),在一个Windows系统中只有一个Task Manager实例
b.Windows的Recycle Bin(回收站),在一个Windows系统中只有一个Recycle Bin实例
c.网站的计数器,一般也是采用单例模式实现,否则难以同步
d.应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则无法实现内容追加
e.数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗
f.多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制
g.操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统
4.5.优缺点
4.5.1.优点
a.由于单例模式在内存中只有一个实例,减少内存开支,特别是一个对象需要频繁地创建销毁时,而且创建或销毁时性能又无法优化,单例模式就非常明显了
b.由于单例模式只生成一个实例,所以,减少系统的性能开销,当一个对象产生需要比较多的资源时,如读取配置,产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决
c.单例模式可以避免对资源的多重占用,例如一个写文件操作,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作
d.单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如,可以设计一个单例类,负责所有数据表的映射处理
4.5.2.缺点
a.单例模式没有抽象层,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现,违反了OCP原则
b.单例类的职责过重,在一定程度上违背了"单一职责原则"
c.滥用单例将带来一些负面问题,如:为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出
4.6.角色及其职责
4.7.模型
4.7.1.模型类图
类图(有Client)
类图(无Client)
4.7.2.代码
package com.dragonsoft.designpattern.create.singleton.model;
public class SingletonObject {
private SingletonObject() {}
private static final SingletonObject SINGLETON_INSTANCE = new SingletonObject();
public static SingletonObject getInstance() {
return SINGLETON_INSTANCE;
}
public void operate(){
System.out.println("do some operate......");
}
}
4.8.示例
4.8.1.饿汉式单例
4.8.1.1.类图
类图(有Client)
类图(无Client)
4.8.1.2.代码
SingletonA.java
package com.dragonsoft.designpattern.create.singleton;
/**
* 饿汉式
* @author lingwh
*
*/
public class SingletonA {
private SingletonA() {}
private static final SingletonA SINGLETONA = new SingletonA();
public static SingletonA getInstance() {
return SINGLETONA;
}
}
Client.java
package com.dragonsoft.designpattern.create.singleton;
import org.junit.Test;
public class Client {
/**
* 测试测试饿汉式单例
*/
@Test
public void fun() {
SingletonA instance1 = SingletonA.getInstance();
SingletonA instance2 = SingletonA.getInstance();
System.out.println(instance1 == instance2);
System.out.println("instance1.hashCode():"+instance1.hashCode());
System.out.println("instance2.hashCode():"+instance2.hashCode());
}
}
4.8.2.懒汉式单例
4.8.2.1.饿汉式单例类图
类图(有Client)
类图(无Client)
4.8.2.2.代码
SingletonB.java
package com.dragonsoft.designpattern.create.singleton;
/**
* 懒汉式:
* 优点:可以实现懒加载
* 缺点:有线程安全问题
* @author lingwh
*
*/
public class SingletonB {
private SingletonB() {}
private static SingletonB singletonB = null;
public static SingletonB getInstance() {
if(singletonB == null) {
singletonB = new SingletonB();
}
return singletonB;
}
}
Client.java
package com.dragonsoft.designpattern.create.singleton;
import org.junit.Test;
public class Client {
/**
* 测试单线程测试懒汉式
*/
@Test
public void fun1() {
SingletonB instance1 = SingletonB.getInstance();
SingletonB instance2 = SingletonB.getInstance();
System.out.println(instance1 == instance2);
System.out.println("instance1.hashCode():"+instance1.hashCode());
System.out.println("instance2.hashCode():"+instance2.hashCode());
}
/**
* 测试多线程测试线程不安全的懒汉式
*/
@Test
public void fun2() {
long begin = System.currentTimeMillis();
//多线程测试单例模式线程是否安全
Thread[] threads = new Thread[10000];
for(int i = 0;i<threads.length;i++){
//创建线程
threads[i] =
new Thread(new Runnable() {
@Override
public void run() {
SingletonB instance = SingletonB.getInstance();
System.out.println("instance.hashCode():"+instance.hashCode());
}
});
}
for(int i=0;i<threads.length;i++){
threads[i].start();//线程启动
}
long end = System.currentTimeMillis();
System.out.println("程序执行时间:" + (end-begin));
}
}
4.8.3.线程安全的懒汉式单例
4.8.3.1.类图
类图(有Client)
类图(无Client)
4.8.3.2.代码
SingletonC.java
package com.dragonsoft.designpattern.create.singleton;
/**
* 线程安全的懒汉式
* @author lingwh
*
*/
public class SingletonC {
private SingletonC() {}
private static SingletonC singletonC;
public static synchronized SingletonC getInstance() {
if(singletonC == null) {
singletonC = new SingletonC();
}
return singletonC;
}
}
Client.java
package com.dragonsoft.designpattern.create.singleton;
import org.junit.Test;
public class Client {
/**
* 测试多线程测试线程安全的懒汉式
* 方法级别的锁:实测执行效率并不是很低
*/
@Test
public void fun() {
long begin = System.currentTimeMillis();
//多线程测试单例模式线程是否安全
Thread[] threads = new Thread[10000];
for(int i = 0;i<threads.length;i++){
//创建线程
threads[i] =
new Thread(new Runnable() {
@Override
public void run() {
SingletonC instance = SingletonC.getInstance();
System.out.println("instance.hashCode():"+instance.hashCode());
}
});
}
for(int i=0;i<threads.length;i++){
threads[i].start();//线程启动
}
long end = System.currentTimeMillis();
System.out.println("程序执行时间:" + (end-begin));
}
}
4.8.4.双重检索懒汉式懒汉式单例
4.8.4.1.类图
类图(有Client)
类图(无Client)
4.8.4.2.代码
SingletonD.java
package com.dragonsoft.designpattern.create.singleton;
/**
* 双重检索懒汉式
* @author lingwh
*
*/
public class SingletonD {
private SingletonD() {}
private static volatile SingletonD singletonD;
public static SingletonD getInstance() {
if(singletonD == null) {
synchronized(SingletonD.class) {
if(singletonD == null) {
singletonD = new SingletonD();
}
}
}
return singletonD;
}
}
Client.java
package com.dragonsoft.designpattern.create.singleton;
import org.junit.Test;
public class Client {
/**
* 测试多线程测试静态双重检索线程安全的懒汉式
* 方法级别的锁:实测执行效率并不是很低
*/
@Test
public void fun() {
long begin = System.currentTimeMillis();
//多线程测试单例模式线程是否安全
Thread[] threads = new Thread[10000];
for(int i = 0;i<threads.length;i++){
//创建线程
threads[i] =
new Thread(new Runnable() {
@Override
public void run() {
SingletonD instance = SingletonD.getInstance();
System.out.println("instance.hashCode():"+instance.hashCode());
}
});
}
for(int i=0;i<threads.length;i++){
threads[i].start();//线程启动
}
long end = System.currentTimeMillis();
System.out.println("程序执行时间:" + (end-begin));
}
}
4.8.5.静态内部类懒汉式单例
4.8.5.1.类图
类图(有Client)
类图(无Client)
4.8.5.2.代码
SingletonE.java
package com.dragonsoft.designpattern.create.singleton;
/**
* 静态内部类懒汉式
* 原理:JVM在装载类的时候是线程安全的
* @author lingwh
*
*/
public class SingletonE {
private SingletonE() {}
public static SingletonE getInstance() {
return SingletonInstacne.INSTANCE;
}
private static class SingletonInstacne {
private static final SingletonE INSTANCE = new SingletonE();
}
}
Client.java
package com.dragonsoft.designpattern.create.singleton;
import org.junit.Test;
public class Client {
/**
* 测试多线程测试静态内部类线程安全的懒汉式
*/
@Test
public void fun() {
long begin = System.currentTimeMillis();
//多线程测试单例模式线程是否安全
Thread[] threads = new Thread[10000];
for(int i = 0;i<threads.length;i++){
//创建线程
threads[i] =
new Thread(new Runnable() {
@Override
public void run() {
SingletonE instance = SingletonE.getInstance();
System.out.println("instance.hashCode():"+instance.hashCode());
}
});
}
for(int i=0;i<threads.length;i++){
threads[i].start();//线程启动
}
long end = System.currentTimeMillis();
System.out.println("程序执行时间:" + (end-begin));
}
}
4.8.6.枚举单例
4.8.6.1.类图
类图(有Client)
类图(无Client)
4.8.6.2.代码
SingletonF.java
package com.dragonsoft.designpattern.create.singleton;
/**
* 枚举实现单例
* @author lingwh
*
*/
public enum SingletonF {
INSTANCE;
public void doSomething() {
System.out.println("doSomething......");
}
}
Client.java
package com.dragonsoft.designpattern.create.singleton;
import org.junit.Test;
public class Client {
/**
* 测试枚举实现单例
*/
@Test
public void fun() {
SingletonF instance1 = SingletonF.INSTANCE;
SingletonF instance2 = SingletonF.INSTANCE;
System.out.println(instance1 == instance2);
System.out.println("instance1.hashCode():"+instance1.hashCode());
System.out.println("instance2.hashCode():"+instance2.hashCode());
//通过单例调用doSomething()
instance1.doSomething();
instance2.doSomething();
}
}
4.9.在开源框架中的应用
JDK8#java.lang.Runtime(饿汉式)
public class Runtime {
private static Runtime currentRuntime = new Runtime();
public static Runtime getRuntime() {
return currentRuntime;
}
private Runtime() {}
}
评论