欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-26 20:33:16
单例模式单例模式饿汉式单例枚举类型构造其他样式的饿汉式单例模式懒汉式单例线程安全问题的解决其他形式单例模式单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)意思讲白了,就是避免线程安全问题,使得类只能有一个对象。同时,这也是一些面试题目,虽然我只是个学生,多学点没得错。饿汉式单例不管我们使用者是否需要这个对象,它都上来先给你创建好这个唯的对象。枚举类型构造直接上代码看:...

单例模式

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

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

饿汉式单例

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

枚举类型构造

直接上代码看:

	@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;
	}
}

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

静态内部类不会随着外部类的初始化一 起初始化,而是要在使用到这个静态内部类时才会初始化
JAVASE-------单例模式

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