设计模式--单例模式

简介:单例模式就是采取一定的方法,保证在整个软件系统中,对某个类只存在一个实例对象,并且该类只提供一个静态的获取其对象实例的方法;

 

单例模式有8种方式:

  • 饿汉式 (静态常量)
  • 饿汉式 (静态代码块)
  • 懒汉式 (线程不安全)
  • 懒汉式 (线程安全,同步方法)
  • 懒汉式 (线程安全,同步代码块)
  • 双重检查
  • 静态内部类
  • 枚举

-----------------------------------------------------分  割  线--------------------------------------------------------

  • 1. 饿汉式(静态常量)
class Singleton {

    // 1.私有化构造器
    private Singleton() {

    }


    // 2.本类内部创建实例
    private final static Singleton singleton = new Singleton();



    // 3.提供一个公开的静态的获取实例的方法
    public static Singleton getSingleton() {
        return singleton;
    }

}



/**
 * 单例模式-饿汉式(静态常量)
 * 优缺点说明:
 * 1.优点:写法比较简单,在类转载时实例化对象,避免了线程同步问题。
 * 2.缺点:在类装载时完成实例化,没有Lazy Loading的效果,如果从始至终
 * 没有实例化这个类,将会造成线程浪费;
 * @param args
 */
public static void main(String[] args) {
    Singleton singleton1 = Singleton.getSingleton();
    Singleton singleton2 = Singleton.getSingleton();
    System.out.println(singleton1==singleton2); //true
    System.out.println(singleton1.hashCode()); //366712642
    System.out.println(singleton2.hashCode()); //366712642
}

-----------------------------------------------------分  割  线--------------------------------------------------------

  • 2.饿汉式(静态代码块)
class Singleton2 {

    // 1.私有化构造器
    private Singleton2() {

    }


    // 2.本类内部创建实例
    private static Singleton2 singleton;


    // 3.静态代码块中创建实例对象
    static {
        singleton = new Singleton2();
    }


    // 3.提供一个公开的静态的获取实例的方法
    public static Singleton2 getSingleton() {
        return singleton;
    }

}


/**
 * 饿汉式(静态代码块)
 * 优缺点说明:
 * 1.优点:写法比较简单,在静态代码块中实例化对象,避免了线程同步问题。
 * 2.缺点:在类装载时完成实例化,没有Lazy Loading的效果,如果从始至终
 * 没有实例化这个类,将会造成线程浪费;
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    Singleton2 singleton1 = Singleton2.getSingleton();
    Singleton2 singleton2 = Singleton2.getSingleton();
    System.out.println(singleton1 == singleton2); // true
    System.out.println(singleton1.hashCode()); // 366712642
    System.out.println(singleton2.hashCode()); // 366712642
}

-----------------------------------------------------分  割  线--------------------------------------------------------

  • 3.懒汉式(线程不安全)
class Singleton3 {

    // 1.私有化构造器
    private Singleton3() {

    }


    // 2.本类内部创建实例
    private static Singleton3 singleton;


    // 3.提供一个公开的静态的获取实例的方法
    public static Singleton3 getSingleton() {
        if (singleton == null) {
            singleton = new Singleton3();
        }
        return singleton;
    }
}



/**
 * 懒汉式(线程不安全) 优缺点说明:
 * 1. 起到了Lazy Loading的效果,但是只能在单线程中使用
 * 2. 如果在多线程下,if (singleton == null) 判断语句块,还未来的及往下执行,另一个线程也通过了这个判断
 * 这时便会出现多个实例,所以在多线程的情况下,不推荐使用这种方式;
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    Singleton3 singleton1 = Singleton3.getSingleton();
    Singleton3 singleton2 = Singleton3.getSingleton();
    System.out.println(singleton1 == singleton2); // true
    System.out.println(singleton1.hashCode()); // 366712642
    System.out.println(singleton2.hashCode()); // 366712642
}

-----------------------------------------------------分  割  线--------------------------------------------------------

 

  • 4.懒汉式(线程安全,同步方法)
class Singleton4 {

    // 1.私有化构造器
    private Singleton4() {

    }


    // 2.本类内部创建实例
    private static Singleton4 singleton;


    // 3.提供一个公开的静态的获取实例的方法
    public static synchronized Singleton4 getSingleton() {
        if (singleton == null) {
            singleton = new Singleton4();
        }
        return singleton;
    }
}



/**
 * 懒汉式(线程安全,同步方法) 优缺点说明:
 * 1. 解决了线程安全的问题
 * 2. 同步代码块的效率太低了
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    Singleton4 singleton1 = Singleton4.getSingleton();
    Singleton4 singleton2 = Singleton4.getSingleton();
    System.out.println(singleton1 == singleton2); // true
    System.out.println(singleton1.hashCode()); // 366712642
    System.out.println(singleton2.hashCode()); // 366712642
}

-----------------------------------------------------分  割  线--------------------------------------------------------

 

  • 5.懒汉式(线程安全,同步方法块)
class Singleton5 {

    // 1.私有化构造器
    private Singleton5() {

    }


    // 2.本类内部创建实例
    private static Singleton5 singleton;


    // 3.提供一个公开的静态的获取实例的方法
    public static Singleton5 getSingleton() {
        if (singleton == null) {
            synchronized(Singleton5.class){
                singleton = new Singleton5();
            }
        }
        return singleton;
    }
}



/**
 * 懒汉式(线程安全,同步方法块)  
 * 1. 解决了线程安全的问题
 * 2. 同步代码块的效率太低了
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    Singleton5 singleton1 = Singleton5.getSingleton();
    Singleton5 singleton2 = Singleton5.getSingleton();
    System.out.println(singleton1 == singleton2); // true
    System.out.println(singleton1.hashCode()); // 366712642
    System.out.println(singleton2.hashCode()); // 366712642
}

-----------------------------------------------------分  割  线--------------------------------------------------------

 

  • 6.双重检查

class Singleton6 {

    // 1.私有化构造器
    private Singleton6() {

    }

    // 2.本类内部创建实例
    private static volatile Singleton6 singleton;

    // 3.提供一个公开的静态的获取实例的方法
    public static Singleton6 getSingleton() {
        if (singleton == null) {
            synchronized(Singleton6.class){
                if (singleton == null) {
                    singleton = new Singleton6();
                }
            }
        }
        return singleton;
    }
}



/**
  * 双重检查
  * 1. 线程安全,延迟加载,效率高
  * 2. 推荐使用这种单例模式
  * @param args
  */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    Singleton6 singleton1 = Singleton6.getSingleton();
    Singleton6 singleton2 = Singleton6.getSingleton();
    System.out.println(singleton1 == singleton2); // true
    System.out.println(singleton1.hashCode()); // 366712642
    System.out.println(singleton2.hashCode()); // 366712642
}

-----------------------------------------------------分  割  线--------------------------------------------------------

 

  • 7.静态内部类
class Singleton7 {

    // 1.私有化构造器
    private Singleton7() {

    }

    // 2.静态内部类创建对象
    private static class SingletonInstance {
        private static final Singleton7 INSTANCE = new Singleton7();
    }


    // 3.提供一个公开的静态的获取实例的方法
    public static Singleton7 getSingleton() {
        return SingletonInstance.INSTANCE;
    }
}



/**
 * 静态内部类
 * 优缺点: 1.这种方式采用类加载的机制来保证初始化实例时只有一个线程 2.静态内部类方式在 Singleton7
 * 类被装载时,不会立即初始化,而是需要在实例化时,调用 getSingleton 才会调用 SingletonInstance
 * 方法,从而完成初始化;
 * 3.类的静态方法只会在类的第一次加载时初始化,所以在这里,JVM机制帮我们保证了线程的安全性,在类进行初始化时,别的线程无法进入;
 * 4.优点:为了避免线程不安全,利用静态内部类特点实现延迟加载,效率高;
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    Singleton7 singleton1 = Singleton7.getSingleton();
    Singleton7 singleton2 = Singleton7.getSingleton();
    System.out.println(singleton1 == singleton2); // true
    System.out.println(singleton1.hashCode()); // 366712642
    System.out.println(singleton2.hashCode()); // 366712642
}

-----------------------------------------------------分  割  线--------------------------------------------------------

 

  • 8.枚举
enum Singleton8{
    INSTANCE;

    public void sayOK(){
        System.out.println(" OK! ");
    }
}



/**
 * 枚举
 * 优缺点:借助JDK 1.5中添加枚举来实现单例模式,不仅能避免多线程同步问题,还能防止反序列化重新创建对象
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    Singleton8 singleton1 = Singleton8.INSTANCE;
    Singleton8 singleton2 = Singleton8.INSTANCE;
    System.out.println(singleton1 == singleton2); // true
    System.out.println(singleton1.hashCode()); // 366712642
    System.out.println(singleton2.hashCode()); // 366712642
    singleton1.sayOK();
}

-----------------------------------------------------分  割  线--------------------------------------------------------

总结:

  • 单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要反复频繁创建销毁的对象,使用单例模式可以提升系统的性能;
  • 当想实例化一个单例类的时候,记住必须使用相应的获取对象的方法,不能使用new;
  • 单例模式的使用场景:
  1. 需要频繁创建和销毁的对象;
  2. 创建对象耗时较长或者资源较多,但又经常使用的对象,工具类对象,频繁访问数据库或文件的对象;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值