设计模式是解决问题的方案,学习现有的设计模式可以做到经验复用。
我的理解的话就是对于java语言的面向对象这一特性的的产物,在不同的环境,需求下对象管理的经验总结;
单例模式是最基本与最基础的一种设计模式,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
其核心思想是:一个类只有一个实例,并提供该实例的全局访问点。
实现方式:
使用一个私有构造函数、一个私有静态变量以及一个公有静态函数来实现。
私有构造函数保证了不能通过构造函数来创建对象实例,只能通过公有静态函数返回唯一的私有静态变量。
最关键的就是构造函数的私有的,也就是不提供对外实例化函数;
以上就是一个最基本的单例模式实现类,参照的是菜鸟教程;
既然我们已经遵守单例模式的规范定义了一个类,那么下面来测试一下是否真正的实现了单例模式:
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 比较,都是 一致的;说明两次获取的对象都是同一个对象,只生成了一个对象;
单例模式的实现有多种方式:
这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。 这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。
在获取实例对象的方法上添加了synchronized 关键字,保证了在多线程下的单例;
此种模式就是我上面举例的,在类装载的时候就进行初始化,没有加锁,执行效率会提高,但是容易产生垃圾对象,当外部调用类中其他静态方法时也会生成对象(虽然很少),造成内存浪费;
此种方式创建单例,将对象的创建放置在静态代码块之内,只有获取当前对象的时候才会创建对象,不会对使用类内其他静态方法造成影响;也不会造成内存浪费;
