Java设计模式

单例模式

2018-10-14  本文已影响4人  yzbkaka

定义

单例模式(Singleton Pattern)是一种比较简单的设计模式,它的定义是:

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

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


单例模式

从图中可以看出,Singleleton是一个单例类,通过private的构造函数来声明一个程序中只产生一个类的对象,并且这个对象是在Singleleton类中自行实例化的在(Singleton中自己使用new Singleton())。单例模式的通用代码如下:

public class Singleton{
    private static final Singleton singleton = new Singleton();  //在内部定义一个静态的对象
    private Singleton{
        //定义私有的构造函数
    }
    public static singleton getSingleton(){  //调用该方法得到对象
        return singleton;
    }
    public static void doSomething(){
        //对象所要操作的动作
    }
}

下面利用单例模式的思想来实际编写一个简单的程序:

public class HeadTeacher{
    private static final HeadTeacher headteacher = new HeadTeacher();  //建立一个班主任对象 
    private HeadTeacher{
        //定义私有的构造函数
    }
    public static HeadTeacher getHeadTeacher(){  //得到该对象的方法
        return headteacher;
    }
    public static void say(){
        System.out.println("Hello students! I am miss Zhang");  //向学生打招呼
    }
}

public class Student{
    public static void main(String[] args){
        for(int i=0;i<5;i++){  //学生周一到周五到学校上课
            HeadTeacher headteacher = HeadTeacher.getHeadTeacher();
            headteacher.say();  //班主任向学生打招呼
        }
    }
}
这个程序是在模仿生活中班主任在每一个工作日向学生打招呼说“Hello students”,这些学生只有一个班主任,因此他们只会听到这位班主任的招呼,而不是其他的班主任。程序的运行结果如下: 简单的单例模式

应用

单例模式的优点主要有以下几个方面:
(1)由于单例模式在内存中只有一个实例,所以减少了内存开支和系统的性能开销。
(2)单例模式可以避免对资源的多重占用。例如写一个文件动作,由于只有一个实例存在内存中,避免了对同一个资源文件的同时写操作。
(3)单例模式可以在系统设置全局的访问点,优化和共享资源访问。例如可以设计一个单例类来负责所有数据表的映射处理。

综合以上的优点,当我们再设计程序时看到需要在一个系统中,要求一个类有且仅有一个对象并且如果出现多个对象就会出现“不良反应”的需求时,就可以使用单例模式。具体的场景如下:
(1)要求生成唯一序号的环境。
(2)在整个项目中需要一个共享访问点或者共享数据。例如一个Web页面上的一个计数器,可以使用单例模式保持计数器的值,并确保线程是安全的。
(3)创建一个对象消耗过多时。
(4)需要定义大量的静态常量和静态方法的环境时。

注意事项

单例模式也有比较明显的缺点,具体如下:
(1)单例模式一般是没有接口的,扩展会很困难,如果要扩展,除了修改代码基本上就没有其他的办法。
(2)单例模式对于测试是不利的。在实际开发中,加入单例模式没有完成,是无法进行程序测试的,因为它既没有接口也不能用其他方式虚拟一个对象。
(3)在高并发的情况下,需要注意单例模式的线程同步问题。单例模式有着不同的实现方式,上面的“班主任打招呼”的例子是不会产生多个实例情况的,但是在某些情况下是必须要考虑线程同步的,举例来说:

public class Singleton{
    private static Singleton singleton = null;
    private Singleton(){
        //构造函数
    }
    public static Singleton getSingleton(){  //返回实例
        if(singleton=null){
            singleton = new Singleton();
        }
        return singleton;
    }
}

在上述代码中是有可能出现线程同步问题的,例如线程A在执行到singleton = new Singleton();这一步时需要等待JVM来创造一个对象,而在等待的时候线程B也在执行,而且正好执行到了if(singleton=null)这一步,由于这时候线程A要创建的对象还没有初始化出来,因此线程B在这里获得的判断条件为真,它就会继续执行下去。这样线程A和线程B都创建了一个对象。

扩展

如果一个类需要很多个对象,则直接new就可以了;如果只需要一个对象,就可以直接使用单例模式,但是如果要求一个类只能产生两个或三个对象时,就需要使用单例模式的扩展——多例模式。

多例模式的定义是产生固定数量对象的模式。在多例模式中我们可以在设计时决定在内存中有多少个实例,方便系统进行扩展,修正。例如在读取文件当中,我们可以在系统启动时完成初始化工作,在内存中启动固定数量的reader实例,然后在需要读取文件时就可以快速的响应。

上一篇 下一篇

猜你喜欢

热点阅读