java设计模式之--单例模式

java设计模式之--单例模式

Scroll Down
小提示,本文编写于  2,225  天前,最后编辑于  1,893  天前,某些信息可能有些出入,仅供参考。

介绍

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。

每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。

总之,选择单例模式就是为了避免不一致状态,避免政出多头。

特性:

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

单例模式保证了全局对象的唯一性,比如系统启动读取配置文件就需要单例保证配置的一致性。

单例模式之自我分析

缺点:

  1. 一般没有接口,扩展很困难,如果想扩展的话,除了修改代码基本上没有第二种方式
  2. 使用的场景比较单调,如果是在多场景不断变化的实例对象最好不要使用单例,数据容易出问题

优点:

  1. 由于只有一个实例对象,所以占用内存很少
  2. 对象不用重复new了,当然于解放了对资源的重复占用,提升了性能
  3. 比类操作更灵活

单例模式之实现

俗话说,说的比唱的好听。为了证明我唱的也很好听,接下来我就以人类的一夫一妻制来具体讲解一下如何实现我的模式~一夫一妻制又称作”单偶婚“,“个体婚”,据说一夫一妻制起源于秦始皇统一天下之后
自大秦一统天下,中国酒实行了一夫一妻制,尤其是在汉朝“罢黜百家,独尊儒术”开始,古人严格执行了这一制度blablabla...(此处省略n字)。咳咳,跑题了,我们接着谈一夫一妻制,哦不,单例模式,首先得有个妻子类:

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获得一个对象。妻子有了,老公Y自然要出场了,其类代码如下:

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!

Y每天回家见到的妻子,都是同一个妻子,不会出现开门后,一看,呦呵,老婆怎么变了?
如有此情况,请速与我联系!

单例模式之优化/问题

有人嫌这样麻烦,因为无论是都使用这个类,都会创建一个instance对象,如果创建这个很耗时,比如需要连接10**9(python的10的9次方写法)次数据库,并且还不一定使用,那该这么办?于是乎有“聪明人”想到如下的方法: 

public class Singleton {
    private static Singleton instance;
    private Singleton (){}

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

是不是感觉很不错,很好?这个是传说中的懒汉模式其实这个有个很大的问题,如果是高并发情况下,可能A线程在创建实例,但是还没获取对象,B此时也在执行,判断也为真,所以又获得一个对象,如此下去,你的妻子会越来越多!没办法了么?不,当然有,且往下看:

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

这种写法确实解决了问题,但是效率么,啧啧,99%情况下不需要同步我会告诉你么?
奇淫技巧:单例模式之反射实现

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;
    }
}

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

一个挺有意思的角度,枯燥的理论换个表达方式理解起来有不一样的效果

参考文章:
设计模式之单例模式(JAVA实现)