关于设计模式
设计模式是解决问题的方案,学习现有的设计模式可以做到经验复用。
我的理解的话就是对于java语言的面向对象这一特性的的产物,在不同的环境,需求下对象管理的经验总结;
单例模式
单例模式是最基本与最基础的一种设计模式,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
其核心思想是:一个类只有一个实例,并提供该实例的全局访问点。
实现方式:
-
使用一个私有构造函数、一个私有静态变量以及一个公有静态函数来实现。
-
私有构造函数保证了不能通过构造函数来创建对象实例,只能通过公有静态函数返回唯一的私有静态变量。
最关键的就是构造函数的私有的,也就是不提供对外实例化函数;
具体实现
package com.test;
/**
* @author: yzp
* @Date: 2019/11/2 12:16
* @Description: 单例模式
*/
public class Singleton {
/**
* 创建一个 Singleton 对象
*/
private static Singleton singleton = new Singleton();
/**
* 私有化构造函数,防止被实例化
*/
private Singleton() {
}
/**
* 提供一个对外的获取此对象的方法
*/
public static Singleton getInstance(){
return singleton;
}
}
以上就是一个最基本的单例模式实现类,参照的是菜鸟教程;
测试
既然我们已经遵守单例模式的规范定义了一个类,那么下面来测试一下是否真正的实现了单例模式:
package test;
import com.test.Singleton;
/**
* @author: yzp
* @Date: 2019/11/2 12:29
* @Description:
*/
public class SingletonTest {
public static void main(String[] args) {
// 获取一个 Singleton 对象 singleton1
Singleton singleton1 = Singleton.getInstance();
// 获取一个 Singleton 对象 singleton2
Singleton singleton2 = Singleton.getInstance();
// 比较 hashCode
if (singleton1 == singleton2){
System.out.println("singleton1 hashCode = " + singleton1.hashCode() );
System.out.println("singleton2 hashCode = " + singleton2.hashCode() );
}
// 比较实际对象
if (singleton1.equals(singleton2)){
System.out.println("单例模式");
}
}
}
控制台输出:
无论是两次获取对象的 hashCode 比较还是 equals 比较,都是 一致的;说明两次获取的对象都是同一个对象,只生成了一个对象;
单例模式的实现有多种方式:
单例模式 -懒汉模式(线程不安全)
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。
单例模式 -懒汉模式(线程安全)
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
在获取实例对象的方法上添加了synchronized 关键字,保证了在多线程下的单例;
单例模式-饿汉模式(线程安全)
此种模式就是我上面举例的,在类装载的时候就进行初始化,没有加锁,执行效率会提高,但是容易产生垃圾对象,当外部调用类中其他静态方法时也会生成对象(虽然很少),造成内存浪费;
单例模式-静态内部类
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){
}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
此种方式创建单例,将对象的创建放置在静态代码块之内,只有获取当前对象的时候才会创建对象,不会对使用类内其他静态方法造成影响;也不会造成内存浪费;