之前给大家讲了关于设计模式的七大原则,这一次给大家带来了设计模式中的单例模式,以后会将23种设计模式一一为大家准备好。接下来让我们来看看单例模式吧。
概念:
就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法静态方法。
单例模式一共有8中方式:
想必这是大家第一次听到有这么多吧,不要慌,其实都是大同小异。
请看
class Singleton{
//1.构造器私有化,外部无法new
private Singleton(){
}
//2.本类内部创建对象实例
private final static Singleton instance = new Singleton();
//3.对外提供一个共有的静态方法 返回实例对象
public static Singleton getInstance(){
return instance;
}
}
优点:比较简单,避免了线程同步问题,但是在类装载的时候就完成了实例化,没有达到lazying loading,如果从未使用过该实例则有可能造成内存浪费 该方法在基于classloader机制避免了线程安全问题
class Singleton{
//1. 构造私有化,外部无法new
private Singleton(){
}
//2. 本类内部创建实例
private static Singleton instance;
static{//静态代码块中创建单例对象
instance = new Singleton();
}
//3. 提供一个共有的静态方法,返回实例对象
public static Singleton getInstance(){
return instance;
}
}
这种与上面的方法类似(静态常量),只不过将实例化过程放在了静态代码块中。优缺点一样和上面方法。
class Singleton{
private static Singleton instance;
private Singleton(){}
// 提供一个静态的公有方法,当使用到方法时,才去创建instance
// 即懒汉式
public static Singleton getInstance(){
if(instance ==null){
instance = new Singleton();
}
return instance;
}
}
优缺点: 起到了Lazying Loading的效果,但是只能在单线程下使用 多线程下if(instance ==null) 有可能造成一个线程正在执行,对象还未创建成功,另外一个线程也通过了这个判断
class Singleton{
// 本地内部创建静态实例
private static Singleton instance;
// 私有化构造方法
private Singleton(){}
// 提供一个静态的共有方法,加入同步处理的代码,解决线程安全问题;
// 懒汉式
public static sychronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
优缺点: 解决了线程安全问题。但是效率太低了,没个线程想要获得类的实例的时候,执行getInstance()方法都要进行同步,而这个方法只执行一次实例化就够了,后面再想要获取实例直接return即可看,方法进行同步效率太低 不推荐使用
class Singleton {
// 本地内部创建静态实例
private static Singleton singleton;
// 私有化构造方法
private Singleton(){}
// 提供一个共有的静态方法 加入同步代码块
prublic static Singleton getInstance(){
if(instancell = null){
sychronized(Singleton.class){
singleton = new Singleton();
}
}
return singleton;
}
}
线程不安全线上环境不可使用
class Singleton{
// 本地内部创建内部实例
private static Singleton instance;
// 私有化构造方法
//提供一个共有的静态方法,加入双重检查代码机制,避免线程安全问题,同时解决懒加载问题
// 保证了安全性 提高了效率
public static Singleton getInstance(){
if(instance == null){
sychronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
优缺点: Double Check 概念是多线程中中开发常用到的,我们在这里就进行了两次instance == null判断,这样就可以保证线程安全了,并且实例化代码只执行一次,下次再访问直接return了,避免反复进行方法同步。 线程安全、延迟加载、效率较高推荐使用
class Singleton{
// 本地内部创建静态实例
private static Singleton instance;
// 构造器私有化
private Singleton(){}
// 写一个静态内部类,该类中有一个静态属性Singleton
private static class SingletonInstance{
private static Singleton INSTANCE = new Singelton();
}
// 提供一个共有的静态方法 直接返回SingletonInstance.INSTANCE
public static Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}
优缺点: 这种方式采用类加载的方式保证了初始化实例时只有一个线程, 静态内部类在Singleton类装载的时候不会立即初始化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化 类的静态属性只会在第一次加载类的时候初始化i,所以在这里JVM保证了线程的安全性 优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高
enum Singleton{
INSTANCE;// 属性
public sayHello(){
System.out.println("~ok~")
}
}
优缺点: 借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。 推荐使用
JDK中java.lang.Runtime就是经典的单例模式(饿汉式)。
好了到这里,单例模式的所有情况就已经讲完了。小伙伴们是否有所收获。