设计模式之单例设计模式

单例设计模式

定义

所谓单例设计模式,就是采取一定的方法保证在整个软件系统中,对某个类智能存在一个对象对象实例,并且该类只提供一个取得其对象的方法(静态的)
单例模式的八种设计方式

  1. 饿汉式(静态常量)
  2. 饿汉式(静态代码块)
  3. 懒汉式(线程不安全)
  4. 懒汉式(线程安全,同步方法)
  5. 懒汉式(线程安全,同步代码块)
  6. 双重检查
  7. 静态内部类
  8. 枚举

饿汉式(静态常量)

public class Test01 {

    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);
    }

}

// 饿汉式(静态变量)
class Singleton {
    // 1.私有化构造器
    private Singleton() {
    }

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

    // 3.对外提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance() {
        return singleton;
    }
}
优点:
	写法简单,在类装载的时候就进行了实例化,避免了线程同步的问题
缺点:
	在类装载的时候完成实例化,类装载的情况很多,不能保证一定会用到这个对象,可能会造成内存的浪费。
总结:
	可以使用,但是不是最优方式。

饿汉式(静态代码块)

public class Test {

    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);
    }
}

// 饿汉式(静态代码块)
class Singleton {
    // 1.私有化构造器
    private Singleton() {
    }

    // 在静态代码块中创建单例对象
    static {
        singleton = new Singleton();
    }

    // 2.在本类内部创建对选哪个实例
    private static Singleton singleton;

    // 3.对外提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance() {
        return singleton;
    }
}
优点:
	和静态常量的方式类似,只不过将创建实例化对象的过程放在了静态代码块中执行,同样是写法简单切避免了线程同步的安全。
缺点:
	同样是可能造成内存浪费。
总结:
	可以使用,但是不是最优方式

懒汉式(线程不安全)

public class Test {

    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);
    }
}


class Singleton {
    // 私有化构造器
    private Singleton() {
    }
    
    // 创建一个singleton的属性,但是不创建实例化对象
    private static Singleton singleton;

    // 提供一个静态的公有方法,在使用该方法时才去创建实例化对象
    public static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}
优点:
	实现了懒加载的机制,解决了可能的内存浪费。
缺点:
	是线程不安全的,只能在单线程情况下使用。当两个线程同时进行到判断对象是否创建时,可能会造成创建多个实例化对象。违背了单例模式的设计初衷。
总结:
	在实际开发时不可以使用。

懒汉式(线程安全)

public class Test {

    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);
    }

}
// 懒汉式(线程安全的)
class Singleton {
    // 私有化构造器
    private Singleton() {
    }

    private static Singleton singleton;

    public synchronized static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }

}
优点:
	解决了线程同步不安全的问题。
缺点:
	但是会降低性能,因为在项目中只需要进行一次实例化即可,如果在返回实例化对象处加锁,则会使其在每次都进行线程不同步,大大消耗了性能。
总结:
	可以使用,线程是安全的,也可以进行多线程访问,但是性能不好,不推荐。

懒汉式(同步代码块)

public class Test {

    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);
    }

}

// 懒汉式(线程不安全)
class Singleton {
    // 私有化构造器
    private Singleton() {
    }

    private static Singleton singleton;

    public  static Singleton getInstance() {
        if (singleton == null) {
            synchronized(Singleton.class) {
                singleton = new Singleton();
            }
        }
        return singleton;
    }

}
结论:
	这个方式同样是不能解决线程安全的问题,不可以使用。

双重检查

public class Test {

    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);
    }

}

// 双重检查
class Singleton {
    // 私有化构造器
    private Singleton() {
    }

    private static Singleton singleton;

    public  static Singleton getInstance() {
        if (singleton == null) {
            synchronized(Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

}
优点:
	可以解决多线程并发的安全问题。
	可以实现懒加载,解决可能出现的内存浪费。
	同时保证了效率,不会每次都是同步的。
	每一次判断实例化是否创建,之后一个线程对类进行锁定,之后在判断对象实例化是否创建,如果第二次判断时还是没有创建,则进行实例化创建。
结论:
	在实际开发中推荐使用。

静态内部类

前提:
1)	在外部类进行装载的时候静态内部类不会进行装载
2)	静态内部类装载的时候是线程安全的
public class Test {

    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);
    }

}

// 静态内部类  完成单例模式
class Singleton {
    // 私有化构造器
    private Singleton() {
    }

    private static Singleton singleton;

    // 一个静态内部类,该类中有一个静态属性Singleton
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    // 提供一个静态的公有方法,直接返回静态内部类中的实例化对象属性
    public  static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }

}
优点:
	1)这种方式采用了类装载的机制来保证初始化实例时只有一个线程。
	2)静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getinstance方法, 才会装载SingletonInstance类,从而完成Singleton的实例化。
	3)类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
	4)避免了线程不安全,利用静态内部类特点实现延迟加载,效率高
总结:
	推荐使用.

枚举方式

public class Test {

    public static void main(String[] args) {
        Singleton singleton1 = Singleton.INSTANCE;
        Singleton singleton2 = Singleton.INSTANCE;
        System.out.println(singleton1 == singleton2);
        singleton1.sayOK();
        singleton2.sayOK();
    }
}

enum Singleton {
    INSTANCE;

    public void sayOK() {
        System.out.println("ok~");
    }
}
优点:
	这借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
总结:
	推荐使用。

注意事项

1)例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
2)当想实例化一一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new
3)单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂 等)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值