在设计模式中,单例模式可以说是最简单的一种了,主要作用是让一个类自己进行对象的创建,而且保证了只有一个对象被创建,适用于那种全局的对象。就相当于创建对象的时候不用再进行new操作了,当然,排除使用一些框架帮我们创建对象时也不使用new。
下面直接说一下几种单例模式。
懒汉式线程不安全单例:
所谓懒汉,就是指当调用的时候才去进行对象的创建,比较节约内存,但这种不好之处就是不支持多线程。
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 class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){
}
public static Singleton getInstance() {
return instance;
}
}
双重校验锁:
这种方式能够实现懒加载,并且效率高,而且能实现多线程。
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){
}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
静态内部类式:
这种方式主要就是应用了静态内部类,实现了双重校验锁的机制,也是利用了类加载的机制,但不同于第三个饿汉式的是这里类被加载了,但是INSTANCE并没有被创建,因为需要显示的调用getInstance方法才会使用静态内部类SingletonInner,此时对象才会被创建。并且这种方式还能实现懒加载的机制。
public class Singleton {
private static class SingletonInner {
private static final Singleton INSTANCE= new Singleton();
}
private Singleton (){
}
public static final Singleton getInstance() {
return SingletonInner.INSTANCE;
}
}
其实在说了这几种后,也紧紧停留在理论上,那么项目中这么使用呢?博主结合一下最近开发时遇到的一个问题用C#来讲解一下。
我这里有一个主窗口,然后其中有一个SQL管理的按钮,点击之后,会弹出一个新的窗口,里面进行SQL管理,然后点击SQL管理里面的语句时,触发单击事件,将SQL语句给传回到主窗口中的textBox1中进行展示。可能有人想说使用一个变量来接收吧,但这里还有一个问题,就是那个SQL管理是个dll文件,我是调用的别人开发的SQL管理dll,所以导致这里要传回到我的主界面,只能进行new对象操作,但是new对象的话,sql语句就无法传进我的主窗口了,只能传到新new的窗口里面,因此这里采用单例模式非常合适不过了。
因此我主窗口使用了单例模式,因为我这里对于延迟加载、多线程目前没啥要求,因此我用哪个方式的单例都可以,我这里用的第三个方式,其余的代码我就不展示了,主要展示一下怎么在项目中使用的。
public partial class MainView : Form
{
private static MainView mainView = new MainView();
private MainView()
{
InitializeComponent();
}
public static MainView GetInstance()
{
return mainView;
}
}
至于选择哪一个单例模式来使用,还是看具体需求,一般来说,不怎么使用第一个第二个,建议直接使用第三个,然后如果需要实现懒加载,可以使用静态内部类的方式,对线程要求高,可以使用双重校验锁的方式。