设计模式-单例模式
1、单例模式的简介
定义:属于创建型模式,一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象
目标:保证一个类仅有一个实例,并提供一个访问它的全局访问点
解决问题:一个类被频繁的创建和销毁
说明:单例类只能有一个实例,必须自己创建自己的唯一实例,必须给所有其他对象提供这一实例
2、懒汉式,线程不安全
定义:最基本最简单的单例模式实现方式,使用实例的时候才会去初始化
优点:简单
缺点:线程不安全,不适合多线程
实现:
//单例类
public class lazyA {
private static lazyA lazya;
/**
* 为了规范,添加空白的构造函数
*/
public lazyA(){
}
public static lazyA getName (){
if(lazya == null){
lazya = new lazyA();
System.out.println("This is a new lazyA");
}else{
System.out.println("This is exist a lazyA");
}
return lazya;
}
public void show(){
System.out.println("How are you");
}
}
//测试方法
public static void main(String[] args) {
lazyA lazyA1 = design.single.lazyA.getName();
lazyA1.show();
System.out.println("========================");
lazyA lazyA2 = design.single.lazyA.getName();
lazyA2.show();
System.out.println("========================");
System.out.println(lazyA1==lazyA2);
}
//测试结果
This is a new lazyA
How are you
========================
This is exist a lazyA
How are you
========================
true
3、懒汉式,线程安全
定义:最基本最简单的单例模式实现方式,使用实例的时候才会去初始化,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步
优点:第一次调用才初始化,避免内存浪费
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率
实现:
//单例类
public class lazyB {
private static lazyB lazya;
/**
* 为了规范,添加空白的构造函数
*/
public lazyB(){
}
public static synchronized lazyB getName (){
if(lazya == null){
lazya = new lazyB();
System.out.println("This is a new lazyB");
}else{
System.out.println("This is exist a lazyB");
}
return lazya;
}
public void show(){
System.out.println("How are you");
}
}
//测试方法
public static void main(String[] args) {
lazyB lazyB1 = design.single.lazyB.getName();
lazyB1.show();
System.out.println("========================");
lazyB lazyB2 = design.single.lazyB.getName();
lazyB2.show();
System.out.println("========================");
System.out.println(lazyB1==lazyB2);
}
//测试结果
This is a new lazyB
How are you
========================
This is exist a lazyB
How are you
========================
true
4、饿汉式
定义:这种方式比较常用,但容易产生垃圾对象,类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了
优点:线程安全,没有锁,效率高
缺点:类加载时就初始化,浪费内存
实现:
//单例类
public class hungry {
public static hungry hungry = new hungry();
private hungry(){
System.out.println("very hungry");
}
public static hungry getHungry(){
System.out.println("me too");
return hungry;
}
public void show(){
System.out.println("hungry show");
}
}
//测试方法
public static void main(String[] args) {
hungry hungry1 = design.single.hungry.getHungry();
hungry1.show();
System.out.println("===============================");
hungry hungry2 = design.single.hungry.getHungry();
hungry2.show();
System.out.println("========================");
System.out.println(hungry1==hungry2);
}
//测试结果
very hungry
me too
hungry show
===============================
me too
hungry show
========================
true
5、枚举
定义:这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法 它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化
优点:简单,容易实现,支持多线程
缺点:JDK1.5后加入的enum特性,不能通过 reflection attack 来调用私有构造方法
实现:
//单例类
public class enumTest {
private enumTest() {
}
static enum singleEnum {
//创建一个枚举对象,该对象为单例
SINGLE_ENUM;
private enumTest enumTest;
private singleEnum() {
System.out.println("this is a enum");
enumTest = new enumTest();
}
public enumTest getEnumTest(){
System.out.println("get enumEnum");
return enumTest;
}
}
public static enumTest getInstance(){
System.out.println("this is a enumTest");
return singleEnum.SINGLE_ENUM.getEnumTest();
}
}
//测试方法
public static void main(String[] args) {
enumTest enumTest1 = enumTest.getInstance();
System.out.println("========================");
enumTest enumTest2 = enumTest.getInstance();
System.out.println("========================");
System.out.println(enumTest1==enumTest2);
}
//测试结果
this is a enumTest
this is a enum
get enumEnum
========================
this is a enumTest
get enumEnum
========================
true
6、双检锁(DCL)
定义:这种方式采用双锁机制,安全且在多线程情况下能保持高性能
优点:性能高
缺点:实现复杂
实现:
//单例类
public class Dcl {
private static volatile Dcl dcl = null;
private Dcl(){
}
public static Dcl getDcl(){
System.out.println(dcl);
System.out.println("one:"+(dcl == null));
if(dcl == null){
synchronized (Dcl.class) {
if (dcl == null) {
dcl = new Dcl();
}
System.out.println("two:"+(dcl == null));
}
}
return dcl;
}
}
//测试方法
public class Test {
public static void main(String[] args) {
Dcl dcl1 = Dcl.getDcl();
System.out.println("===============================");
Dcl dcl2 = Dcl.getDcl();
System.out.println("========================");
System.out.println(dcl1==dcl2);
}
}
//测试结果
null
one:true
two:false
===============================
design.single.Dcl@4554617c
one:false
========================
true
7、静态内部类
定义:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用
实现:
//单例类
public class StaticTest {
private static final StaticTest STATIC_TEST = new StaticTest();
private StaticTest(){
System.out.println("one StaticTest");
}
public static final StaticTest getStaticTest(){
System.out.println("two StaticTest");
return StaticTest.STATIC_TEST;
}
}
//测试方法
public static void main(String[] args) {
StaticTest staticTest1 = StaticTest.getStaticTest();
System.out.println("==============================");
StaticTest staticTest2 = StaticTest.getStaticTest();
System.out.println("==============================");
System.out.println(staticTest1==staticTest2);
}
//测试结果
one StaticTest
two StaticTest
==============================
two StaticTest
==============================
true

浙公网安备 33010602011771号