美文网首页
设计模式[1]-单例模式-Singleton Pattern

设计模式[1]-单例模式-Singleton Pattern

作者: 郭寻抚 | 来源:发表于2017-02-20 17:01 被阅读58次

    1. 单例模式简介

    单例模式(Singleton Pattern)是创建型模式(Creational Pattern)的一种,也是最简单的设计模式。顾名思义,单例模式就是只有一个实例,单例类自己创建唯一的实例,并且向其它对象提供这个实例。

    单例模式广泛应用于线程池、缓存、日志对象等场景,这些应用场景基本都涉及到资源管理。

    2. 单例模式的写法

    茴字有四种写法,单例模式也有N种写法,这里我们只准备说三种线程安全的单例模式,分别是饿汉方式、内部类方式、枚举类方式。

    2.1 饿汉方式

    所谓饿汉,就是明明我就在这里,却没有人来勾搭。单例类在被装载时,单例对象就被实例化,即使永远没人调用,是为饿汉。人们说它的缺点是在没被调用之前实例就被创建了,占用了内存资源;但单例模式占用的资源和内存的价格比起来,实在不值一提。

    package org.patterns.creational.singleton;
    
    public class SingleObject {
    
        // 创建单例对象,注意static修饰符。所谓的饿汉模式。
        private static SingleObject instance = new SingleObject();
    
        // 将构造器声明成为private,使其不能通过new操作符来操作。
        private SingleObject(){}
    
        //获取实例的方法,静态的成员方法。
        public static SingleObject getInstance(){
            return instance;
        }
    
        // 单例提供的功能
        public void showMessage(){
            System.out.println("Hello World!");
        }
    }
    

    2.2 内部类方式

    内部类的方式保证了仅当单例类被调用时才实例化对象,同时也保证了线程安全;它利用classloader的机制来保证初始化instance时只有一个线程;当getInstance方法被调用时,内部类SingletonHolder才会被装载,从而实例化单例类。

    内部类的方式,还能防止通过反射和反序列化的方式获取额外的实例。

    public class InnerSingleton {
    
        // 私有构造器
        private InnerSingleton(){}
    
        // 内部类
        private static class SingletonHolder {
            private static final InnerSingleton INSTANCE = new InnerSingleton();
        }
    
        //获取实例的方法,静态的成员方法。
        public static final InnerSingleton getInstance(){
            return SingletonHolder.INSTANCE;
        }
    
        // 单例提供的功能
        public void showMessage(){
            System.out.println("Hello World!");
        }
    }
    

    2.2 枚举类方式

    枚举类方式是《Effective Java》一书所倡导的,需要JDK1.5+的支持。它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。

    public enum EnumSingleton {
        INSTANCE;
    
        // 单例提供的功能
        public void showMessage(){
            System.out.println("Hello World!");
        }
    }
    

    3. 单例模式的注意事项

    • 不同的单例写法,在创建实例的时候,有可能是线程不安全的,可能会导致创建多个实例。

    • 单例不是单线程,单例类也可以被多线程并发地调用;Spring中声明的Bean,默认都是单例模式。如果单例类的多个方法存在资源竞争的情况,那么也许需要引入锁机制来解决。

    • 如果单例类实现了Serializable接口,如果不做处理,反序列化得到的实例,和序列化之前的实例,并不是同一个,他们的内存地址不相同,这违背了单例模式的初衷。Java的序列化机制提供了一个钩子方法,即私有的readresolve方法,允许我们来控制反序列化时得到的对象。通过这个机制,可以使得反序列化得到的实例,就是唯一的实例。下面的链接里,有相关的介绍。http://www.jianshu.com/p/1d73b49a8a1f

    (完)

    相关文章

      网友评论

          本文标题:设计模式[1]-单例模式-Singleton Pattern

          本文链接:https://www.haomeiwen.com/subject/zieewttx.html