当前位置: 移动技术网 > IT编程>开发语言>Java > JAVASE-------单例模式

JAVASE-------单例模式

2020年07月17日  | 移动技术网IT编程  | 我要评论

单例模式

单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)

意思讲白了,就是避免线程安全问题,使得类只能有一个对象。同时,这也是一些面试题目,虽然我只是个学生,多学点没得错。

饿汉式单例

不管我们使用者是否需要这个对象,它都上来先给你创建好这个唯的对象。

枚举类型构造

直接上代码看:

	@Test
	public void fun() {
		SEX sex=SEX.FEMALE;
		SEX sex1=SEX.FEMALE;
		System.out.println(sex==sex1);//堆内存的地址指向都是相同的,说明是同一个对象
	}
	enum SEX{
		MALE,FEMALE;
	}
	/*
	 *这个例子说明,不管怎么样,枚举类型的对象只有一个
	 * */

打印的结果就是true,说明,枚举类型数据就是恶汉式的一种
单例模式的

	/*
	 *上述例子如果不够饿汉
	 *来看看下面的例子
	 * */
	@Test
	public void fun2() {
		COLOR.println();
	}
	enum COLOR{
		WHITE("白色"),BLACK("黑色");
		private String colorName;
		COLOR(String colorName) {
			this.colorName=colorName;
		}
		public static void println() {
			System.out.println("枚举被调用");
		}
		
		public String toString() {
			
			return name()+colorName;
		}
	}

其他样式的饿汉式单例模式

不仅如此,不需要用到枚举对象,但是,他直接创建出来,恶汉模式的典型
jdk1.5之前,枚举类型未更新时,传统单例如下:

样式二
①构造器私有化
②用一个全局的静态的常量,来保存这个唯一-的实例对象

	class Student{
	public static final Student stu=new Student();
	private Student() {}//私有化构造器,防止new
	}
	@Test
	public void fun3() {
		Student s1=Student.stu;
		Student s2=Student.stu;
		System.out.println(s1+"--"+s2);
		System.out.println(s1==s2);
		//运行结果:
		//com.test.Student@18769467--com.test.Student@18769467
		//true
	}

当然,还有一种样式:

样式三
①构造器私有化
②私有化成员的静态变量
③创建静态的方法,返回静态全局变量

class Student{
	private static final Student INSTANCE = new Student();//私有化静态常量
	private Student(){}//私有化构造器
	public static Student getInstance() { 
			return INSTANCE ;
	}
}

懒汉式单例

延迟创建对象,当使用者(调用者)要用到这个对象的时候再去创建

样式一
①构造器私有化
②私有化成员的静态变量(注意final没有了,不需要初始化)
③创建静态的方法,判断后根据情况返回

class LazyClass{
	private static LazyClass lazyClass;
	//public static final Student INSTANCE = new Student();这是懒汉式
	/*
	 1、 上一步与饿汉式不同不仅仅在于修饰符public和private上
	 2、更大的不同在于final取消了,final修饰上去就需要new 初始化出来,就不属于懒汉式
	 */
	private LazyClass(){}//私有化构造器
	public synchronized static LazyClass getInstance() {
		//return new LazyClass();这是错误的理念  不符合懒汉式的概念
		if(lazyClass==null) {
			lazyClass=new LazyClass();
		}//否则就直接输出啦
		return lazyClass;
	} 
}

线程安全问题的解决

与饿汉式最大的不同就是final修饰的静态成员变量,这里如果用final修饰,则需要初始化(final的特性),则不符合“需要再创建”的概念。
同时,需要注意的就是synchronized的引入,因为多个用户线程涉及进入后lazyClass==null这个判断也就会导致线程的问题。
当然这里的锁的范围太大了,导致性能有损,优化版如下

public static LazyClass getInstance() {
		if(lazyClass==null){
			//return new LazyClass();
			synchronized(LazyClass.class) {
				//这里不能用this,因为static静态资源先加载,this空指向,可以用反射
				if(lazyClass==null) {
					lazyClass=new LazyClass();
				}//否则就直接输出啦
			}
		}
		return lazyClass;
	} 

其他形式

利用内部类的特性(用到才会创建)
代码如下

class Lazy2Class{
	private Lazy2Class() {}
	private static class Inner{
		private static final Lazy2Class instance=new Lazy2Class();
	}
	public static Lazy2Class getInstance() {
		return Inner.instance;
	}
}

内部类和外部类是两个独立的类(通过字节码文件可以看出来),没有被调用的时候,就不会创建

静态内部类不会随着外部类的初始化一 起初始化,而是要在使用到这个静态内部类时才会初始化
在这里插入图片描述

本文地址:https://blog.csdn.net/BlackBtuWhite/article/details/107349037

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网