设计模式之单例模式

什么是设计模式

设计模式简单来说就是工程师们经过长期编程,总结的一套固定的编程模式,就像盖房子,本来是随便盖的,但是经过长期实践,建筑者们形成了一套建筑的固定套路,比如哥特式建筑怎么建,四合院怎么建等等。
对应到程序员的软件工程行业,我们其实也是在建造“屋子”,这套设计模式就是我们编程的基本思路。
设计模式有很多种,这里介绍其中最简单也最常用的单例模式。

单例模式即,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。

单例模式实现

懒汉模式(单线程,类加载时不初始化,线程不安全)

public class LazySingleton  {

    private static LazySingleton  instance = null;

    private LazySingleton () {
    }

    public static LazySingleton  getInstance() {
        if (instance == null) {
            instance = new LazySingleton ();
        }
        return instance;
    }
}

由于单例模式下,该对象只能生成一次,所以重构该类的默认构造方法为Private,但是这样又导致其他类无法访问,所以定义一个public的获取对象的方法getInstance(),该方法表明,当对象不存在时new一个类对象,否则返回对象,这样就实现了只能创建一个实例。
在其他类中,调用这个方法获取该类的实例。


测试类:

public class TestSingletom {

    public static void main(String[] args) {
        LazySingleton  s1 = LazySingleton .getInstance();
        LazySingleton  s2 = LazySingleton .getInstance();
        if(s1==s2){
            System.out.println("创造的是相同的对象");
        }else{
            System.out.println("创造的是不同的对象");
        }
    }
}
//返回结果为:
创造的是相同的对象

懒汉模式进阶版本(单线程,单线程,类加载时不初始化)

public class LazySingleton  {

    private static LazySingleton  instance = null;

    private LazySingleton () {
    }

    public static synchronized LazySingleton  getInstance() {
        if (instance == null) {
            instance = new LazySingleton ();
        }
        return instance;
    }
}

这里和前一个模式的唯一区别在于新加了一个synchronized,这是因为在多线程的情况下,如果两个线程同时运行到判断instance是否为null的if语句时,并且instance的确没有创建时,那么两个线程都会创建一个实例,此时Singleton就不能满足单例模式的要求了。
为了保证在多线程环境下我们还只能得到类的一个实例,需要加上一个同步锁。


饿汉模式(在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快)

public class EagerSingleton {
    //饿汉单例模式
    //在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快
private static EagerSingleton instance = new EagerSingleton();
//静态私有成员,已初始化

private EagerSingleton() 
{
    //私有构造函数
}

public static EagerSingleton getInstance()    
//静态,不用同步(类加载时已初始化,不会有多线程的问题)
{
    return instance;
}
}

这种方法不会有线程问题,但是缺点是它不是一种懒加载模式式(lazyinitialization),单例会在加载类后一开始就被初始化,即使客户端没有调用 getInstance()方法。


最优办法:静态内部类 实现单例模式

public class Singleton5 {

    private static class SingletonHolder {
        private static final Singleton5 INSTANCE = new Singleton5();
    }

    private Singleton5() {
    }
    public static final Singleton5 getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

由于 SingletonHolder 是私有的,除了 getInstance() 之外没有办法访问它,因此它是懒汉式的;同时读取实例的时候不会进行同步,没有性能缺陷;


另外:
有人提问,例模式跟全局变量有什么区别?

他们的区别在于:全局变量是一个变量,存在于某个具体的类中,而单例是一个对象,可以存在于整个应用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值