写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用,主要是下面的UML图可以起到大作用,在你学习过一遍以后可能会遗忘,忘记了不要紧,只要看一眼UML图就能想起来了。同时也请大家多多指教。
单例模式(Singleton)
是一种创建型模式。
目录
一、概述
二、如何使用
三、举例---懒汉式
四、举例---饿汉式
一、概述
1、保证一个类仅有一个实例,并提供一个访问它的全局访问点;2、在一些场景下,类的实例化应该由自己决定,而不是外部决定的;3、通常我们可以定义一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的方法就是,让此对象自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法;4、单例模式封装了他的唯一实例,所以它可以严格地控制客户怎样访问它以及何时访问它。简单地说就是对唯一实例的受控访问。
1.1、主要的角色只有一种:
- 需要使用单例模式的对象(单个):其中实现方式有两种,分为懒汉式和饿汉式。
1.2、从上述理论看出使用单例模式主要有2点:
- 这个对象,它应当可以自己实例化自己
- 同时它应当不可以被其他对象实例化
1.3、直观的理解上这个对象的关系情况如下:
1.4、从技术实现的角度看,对象的UML图如下:
二、如何使用
- 隐藏它的构造方法,使得其他对象无法实例化它
- 给它自己定义一个获取它自己实例的接口,供其他对象使用
三、举例---懒汉式
(用Java实现)
懒汉式单例:
//懒汉式单例
public class Singleton1 {private volatile static Singleton1 instance; //volatile修饰,用来避免一些多线程场景下的问题private Singleton1() {//将构造函数私有化,禁止其他对象实例化它自己}//使得其他类可以得到该实例public static Singleton1 getInstance() { //用static修饰的方法可以直接通过 类名.方法名 去访问,而无需new对象if (instance == null) { //实例化被延迟到第一次访问时,并且之后再访问就不会再实例化了synchronized (Singleton1.class) { //synchronized修饰,用来避免一些多线程场景下的问题if (instance == null) {System.out.println("实例化Singleton1"); //标记一下,用来在测试的时候判断被实例化了几次instance = new Singleton1();}}}return instance;}
}
主程序(发起请求的类):
public class Main {public static void main(String[] args) {//懒汉式Singleton1 s1 = Singleton1.getInstance();Singleton1 s2 = Singleton1.getInstance();System.out.println(s1 == s2);//饿汉式
// Singleton2 s3 = Singleton2.getInstance();
// Singleton2 s4 = Singleton2.getInstance();
// System.out.println(s3 == s4);}
}
四、举例---饿汉式
(用Java实现)
饿汉式单例:
//饿汉式单例
public class Singleton2 {//被static修饰的代码,在程序初始化阶段时就会运行此代码,并且只运行一次,这样保证了只有一个实例private static Singleton2 instance = new Singleton2();private Singleton2() {//将构造函数私有化,禁止其他对象实例化它自己}//使得其他类可以得到该实例public static Singleton2 getInstance() {return instance;}
}
主程序(发起请求的类):
public class Main {public static void main(String[] args) {//懒汉式
// Singleton1 s1 = Singleton1.getInstance();
// Singleton1 s2 = Singleton1.getInstance();
// System.out.println(s1 == s2);//饿汉式Singleton2 s3 = Singleton2.getInstance();Singleton2 s4 = Singleton2.getInstance();System.out.println(s3 == s4);}
}
这里就不再举例了,可以把上面的Java例子复制到你本地,运行main函数试一下加深理解。这些代码都是我自己学习的时候根据一些教材手敲的,不存在bug可以直接运行。
如果觉得本文还不错,就请点个赞吧!如果有建议,也请评论指教和讨论!