单例模式

发布时间: 更新时间: 总字数:1093 阅读时间:3m 作者: IP属地: 分享 复制网址

Ensure a class has only one instance,and provide a global point of access to it.(确保其某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)

单例模式介绍

单例模式的通用类图如下:

singleton

Singleton类称为单例类,通过使用private的构造函数确保了在一个应用中只产生一个实例,并且是自行实例化的。

单例模式分析

缺点:

  • 一般没有接口,扩展很困难,如果想扩展的话,除了修改代码基本上没有第二种方式。当然了,特殊情况下,我也可以实现接口、被继承等,这个需要你们自行判断。
  • 测试不便。在并行开发中,如果你们没有把我完成,那么是没有办法进行测试的。
  • 还有一点,我与单一职责原则也有冲突,一个类本应实现一个逻辑,不该关心是否是单例的,是不是要单例取决于环境,但是我把单例和业务逻辑融合在一个类中了。

优点:

  • 对唯一实例的受控访问。由于我的类封装了我唯一的实例,所以可以严格控制用户以及何时访问它。
  • 缩小名空间。我可以避免那些存储唯一实例的全局变量污染名空间。
  • 允许对操作和表示的精化。
  • 允许可变数目的实例。
  • 比类操作更灵活。

单例模式之实现

实现方式有多种:懒汉模式、饿汉模式、静态内部类(java)模式等

Golang

Java

public class Wife{
    private static final Wife wife = new Wife();

    // 这里是私有的
    private Wife(){
    }
    public static Wife getInstance(){
        return wife;
    }
    public static void say(){
        System.out.println("I am Y's wife!");
    }
}

通过定义一个私有访问权限的构造函数,可以避免被其他类new出来一个对象,而Wife自己可以new一个对象出来,其他的类对该类的访问可以通过getInstance获得一个对象。调用代码如下:

public class Y{
    public static void main(String[] args) {
        for (int day=0; day<3;day++ ) {
            Wife wife = Wife.getInstance();
            wife.say();
        }
    }
}

运行结果如下:

I am Y's wife!
I am Y's wife!
I am Y's wife!

优化实现

public class Singleton {
    private static Singleton instance;
    // 这里是私有的
    private Singleton (){}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
  • synchronized 优化
public class Singleton {
    private static Singleton instance;
    private Singleton (){}
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

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

这种写法确实解决了多线程同时初始化多个实例的问题,效率相对会低些。

单例模式之反射实现

public class Singleton{
    private static Singleton singleton;
    static{
        try{
            class cl = class.forName(Singleton.class.getName());
            //获得无参构造
            Constructor con = cl.getDeclaredConstructor();
            //设置无参构造是可访问的
            con.setAccessible(true);
            //产生一个实例对象
            singleton = (Singleton)con.newInstance();
        }
        catch(Exception e)
        {

        }
    }

    public static Singleton getSingleton(){
        return singleton;
    }
}

通过获得类构造,然后设置访问权限,生成一个对象,然后提供外部访问,保证内存对象单一。

单例模式之枚举类型实现

其实,从Java1.5发行版起,实现Singleton还有一种方法,只需要编写一个包含单个元素的枚举类型:

//Enum singleton - the preferred approach
public enum Singleton{

    INSTANCE;

}

这种方法在功能上与公有域方法相近,但是它更为简洁,无偿的提供了序列化机制,绝对防止多次实例化,即使是在面对复杂的序列化或者反射攻击的时候。虽然此方法未被采用,但是单元素的枚举类型已经成为了实现Singleton的最佳方法。

Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数