这里我使用在how2j上部分解答加上自己写的一些代码,我会加上我自己的理解给大家最简单的解答。
这里的代码环境设定在LOL中。
其有一个怪叫大龙GiantDragon,只有一只,所以该类,只能被实例化一次。
我们用这个来做代码的示范。
单例模式定义
单例模式又叫做 Singleton模式,指的是一个类,在一个JVM里,只有一个实例存在。
最终造成影响很简单,就是
外部无法通过new 得到新的实例。
我们实现的方法是通过
私有化构造方法
实现的。
构造方法晓得不?这个不知道我们可以百度或者再写一篇给你介绍介绍。
单例模式核心三要素(面试重点)
- 私有化构造方法
- 定义私有静态 (类)属性指向实例
- public static(公共静态(或者类))的 (getInstance)方法,返回第二步的静态属性
如果不理解,我们可以通过代码进一步深入理解
饿汉单例模式
GiantDragon 提供了一个public static的getInstance方法,外部调用者通过该方法获取定义的对象,而且每一次都是获取同一个对象。 从而达到单例的目的。
这种单例模式又叫做饿汉式单例模式,无论如何都会创建一个实例
package charactor;
public class GiantDragon {
//*1 私有化构造方法
private GiantDragon() {
}
//*2 准备一个类属性,指向一个实例化对象
private static GiantDragon instance = new GiantDragon();
//*3 公共静态方法 提供调用者获取内部实例的对象
public static GiantDragon getInstance() {
return instance;
}
}
懒汉单例模式
懒汉式单例模式与饿汉式单例模式不同,只有在调用getInstance的时候,才会创建实例。
package charactor;
public class GiantDragon {
//**1 私有化构造方法
private GiantDragon() {
}
//**2 定义一个类属性,用于指向一个实例化对象,暂时指向null
private static GiantDragon instance;
//**3 公共静态(类)方法,用于返回实例对象
public static GiantDragon getInstance() {
//第一次访问,发现instance没有指向任何对象,此时进行初始化
if (null == instance) {
instance = new GiantDragon();
}
//返回instance指向的对象
return instance;
}
}
饿汉和懒汉单例模式的调用方式
调用的方式都是相同的,并且生成的都是的单一对象。
package charactor;
public class TestGiantDragon {
public static void main(String[] args) {
//GiantGragon g = new GiantGragon();//不能直接用new创建对象
//只能通过getInstance得到一个对象
GiantDragon g1 = GiantDragon.getInstance();
GiantDragon g2 = GiantDragon.getInstance();
GiantDragon g3 = GiantDragon.getInstance();
//都是同一个对象
System.out.println(g1 == g2);//true
System.out.println(g1 == g3);//true
System.out.println(g2 == g3);//true
}
}
饿汉单例模式和懒汉单例模式的区别
饿汉式,是立即加载的方式,无论是否会用到这个对象,都会加载。
如果在构造方法里写了性能消耗较大,占时较久的代码,比如建立与数据库的连接,那么就会在启动的时候感觉稍微有些卡顿。
懒汉式,是延迟加载的方式,只有使用的时候才会加载。 并且有线程安全的考量。
使用懒汉式,在启动的时候,会感觉到比饿汉式略快,因为并没有做对象的实例化。 但是在第一次调用的时候,会进行实例化操作,感觉上就略慢。
看业务需求,如果业务上允许有比较充分的启动和初始化时间,就使用饿汉式,否则就使用懒汉式。
单例模式小练手
题目:
使用饿汉式单例模式, 把Hero类改造成为单例模式
使用懒汉式单例模式,把Item类改造成为单例模式
这里我们就不给Hero和Item里增加其他多余属性了。
老规矩,我们先自己写然后再对照答案。
这个是饿汉单例模式
package charactor;
public class SingleHero {
//不用写主函数
//饿汉汉单例模式
//1. 构造方法私有化,无返回值
private SingleHero() {
}
//2. 定义一个静态(类)属性指向实例,同时新建一个实例
private static SingleHero instance = new SingleHero();
//3. 定义一个公开静态(类)方法让外部可以调用,返回类型是类类型
public static SingleHero getInstance() {
return instance;
}
//4.使用方法是(不在本类里使用)
//SingleHero s = SingleHero.getInstance();
}
这个是懒汉单例模式
package charactor;
public class SingleItem {
//不用写主函数
//懒汉单例模式
//1. 私有化构造函数,无返回值
private SingleItem() {
}
//2. 私有类属性指向实例对象,懒汉此时懒得不创建实例
private static SingleItem instance;
//3. 公共类 (静态)方法用来给外部调用创建实例,返回是类属性
public static SingleItem getInstance() {
//首次判断instance不存在则创建
if (null == instance) {
instance = new SingleItem();
}
//返回实例
return instance;
}
//4.使用这个来创建实例,在其他class的main里
//SingleItem s = SingleItem.getInstance();
}