单例模式

单例模式

单例模式介绍

代码实现的好文章

单件模式能够保证某一类型对象在系统中的唯一性,即某类在系统中只有一个实例。

它的用途十分广泛,打个比方,我们开发了一个简单的留言板,用户的每一次留言都要将留言信息写入到数据库中,最直观的方法是没次写入都建立一个数据库的链接。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例

1.私有化构造函数,不让其他程序创建的对象初始化。(当构造函数私有后,我们不能在外部类中实例化这个类,也就是不能创建这个类的对象,只能在本类内部创建对象,然后对外提供返回对象的方法,此时提供的对象是唯一的。)(构造函数就是跟类名一样的函数)
2.在本类中new一个静态本类对象。
3.定义一个静态成员函数,它的功能是让其他程序可以通过这个函数获取到本类的对象

  • 一种叫饿汉模式 也就是在类加载的时候就饿了,非要创建实例,
    不考虑创建对象的内存开销

  • 二种叫懒汉模式 也就是,类加载时绝对不会创建实例的,
    只有在需要使用的时候才创建实例对象.

  • 总结一下就是
    饿汉式:我很饿,我一上来就要new个对象!
    懒汉式:我先不new对象,等我干活的时候,我再去new

懒汉模式

```java
// Version 1
public class Single1 {
    private static Single1 instance;
    public static Single1 getInstance() {
        if (instance == null) {
            instance = new Single1();
        }
        return instance;
    }
}
// Version 1.1
// 构造器改为私有的,这样能够防止被外部的类调用
//每次获取instance之前先进行判断,如果instance为空就new一个出来,否则就直接返回已存在的instance
public class Single1 {
    private static Single1 instance;
    private Single1() {}
    public static Single1 getInstance() {
        if (instance == null) {
            instance = new Single1();
        }
        return instance;
    }
}
// Version 2 
//synchronized关键字之后,getInstance方法就会锁上
//避免了Version1中,可能出现因为多线程导致多个实例
public class Single2 {
    private static Single2 instance;
    private Single2() {}
    public static synchronized Single2 getInstance() {
        if (instance == null) {
            instance = new Single2();
        }
        return instance;
    }
}
// Version 3 
//双重检查
public class Single3 {
    private static Single3 instance;
    private Single3() {}
    public static Single3 getInstance() {
        if (instance == null) {
            synchronized (Single3.class) {
                if (instance == null) {
                    instance = new Single3();
                }
            }
        }
        return instance;
    }
}

第一个if (instance == null),其实是为了解决Version2中的效率问题,只有instance为null的时候,才进入synchronized的代码段——大大减少了几率。
第二个if (instance == null),则是跟Version2一样,是为了防止可能出现多个实例的情况

// Version 4 
//volatile关键字的一个作用是禁止指令重排,把instance声明为volatile之后,对它的写操作就会有一个内存屏障(什么是内存屏障?),这样,在它的赋值完成之前,就不用会调用读操作。
//注意:volatile阻止的不singleton = new Singleton()这句话内部[1-2-3]的指令重排,而是保证了在一个写操作([1-2-3])完成之前,不会调用读操作(if (instance == null))。
public class Single4 {
    private static volatile Single4 instance;
    private Single4() {}
    public static Single4 getInstance() {
        if (instance == null) {
            synchronized (Single4.class) {
                if (instance == null) {
                    instance = new Single4();
                }
            }
        }
        return instance;
    }
}

饿汉式

//饿汉式实现

public class SingleB {

    private static final SingleB INSTANCE = new SingleB();

    private SingleB() {}

    public static SingleB getInstance() {

        return INSTANCE;

    }

}
  • 饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变。懒汉式如果在创建实例对象时不加上synchronized则会导致对对象的访问不是线程安全的

  • 懒汉式是延时加载,他是在需要的时候才创建对象,而饿汉式在虚拟机启动的时候就会创建,饿汉式无需关注多线程问题,写法简单明了,能用则用。真正用到的时候才去建这个单例对象,“饿汉式”是在不管用不用得上,一开始就建立这个单例对象

饿汉式有两大缺点:

1.资源的占用:
饿汉模式 在类创建的就得new好它的静态成员对象 故占用空间

2.线程安全

其他

// Effective Java 第一版推荐写法
//静态内部类

public class Singleton {
    private static class SingletonHolder {
        private static Singleton INSTANCE = new Singleton();
    }

    private Singleton (){}
    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
// Effective Java 第二版推荐写法
//枚举类
//创建枚举实例的过程是线程安全的
//但是不能被继承
public enum SingleInstance {
    INSTANCE;
    public void fun1() { 
        // do something
    }
}
// 使用
SingleInstance.INSTANCE.fun1();

工厂模式

1、创建一个接口:
2、创建实现接口的实体类。
3、创建一个工厂,生成基于给定信息的实体类的对象。
4、使用该工厂,通过传递类型信息来获取实体类的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值