这个模式相信大家肯定不陌生了,而且相对来说,也是比较好理解的一个创建型设计模式,对于单例模式,大家经常说的一个比喻就是,类的计划生育。那么,什么是单例呢?
单例模式就是保证一个类仅存在一个实例,比提供一个用于访问它的对外接口。
那什么时候使用单例模式呢?
当我们的程序需要实例化一个对象,并且希望他仅仅存在一个实例的时候,就可使用次设计模式。例如,某些视频播放器,无论你点开了多少个视频文件,仅仅存在一个播放窗口来播放你最后点开的视频,这就是单例模式的体现。
下面我们简单模仿一下:
首先我在一个窗口中添加一个按钮,当我点击这个按钮的时候,弹出一个新的窗体
JFrame f = new JFrame(); // 实例化一个窗体
f.setSize(500, 300); // 设置窗体的大小
JPanel p = new JPanel(); // 实例化一个面板,用于存放组件
p.setLayout(new FlowLayout()); // 设置面板布局
JButton b = new JButton("button"); // 实例化一个按钮
b.setSize(30, 10);
b.addActionListener(new Main()); // 添加点击事件
p.add(b); // 将按钮添加到面板
f.add(p); // 将面板添加到窗体
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置窗体关闭模式
f.show(); // 显示窗体
这个时候,会显示一个简单的窗体,如图:
当我点击按钮的时候,实例化一个新的窗体:
JFrame f2 = new JFrame();
f2.setSize(100, 60);
f2.show();
我实例化新窗体的时候,就是通过new的方式,但是进一步的想,如果我不加限制的点击这个按钮,它就会一直实例化,从而出现多个窗体。如果将这个简单的程序设计为,点击按钮,弹出一个工具箱,出现上述现象是不是就显得很糟糕了。如图:
这里,我们就可以用到单例模式了,那么单例怎么写呢。
1、首先重写这个窗体,并且声明一个私有的静态的自身变量
2、将它的构造方法改为私有
3、提供一个公开对外的静态方法,用于获取这个自身的实例化对象
代码如下:
public class MyFrame extends JFrame {
private static MyFrame f;
private MyFrame() {
}
public static JFrame creatMyFrame() {
if (f == null) {
f = new MyFrame();
}
return f;
}
}
当我再次实例化时:
JFrame f2 = MyFrame.creatMyFrame();
f2.setSize(100, 60);
f2.show();
这样,无论我点击多少次,也只会创建一个窗体了。
然而,这种写法不是线程安全的,什么意思呢,就是对于多线程的时,可能还会造成重复创建的意外情况,因此,我们需要改写一下:
public class MyFrame extends JFrame {
private static MyFrame f;
private MyFrame() {
}
public static JFrame creatMyFrame() {
if (f == null) {
synchronized (JFrame.class) {
if (f == null) {
f = new MyFrame();
}
}
}
return f;
}
}
好了,这样就可以了,至于什么是多线程和线程安全,在这里就不进行讲述了,我们只说设计模式嘛。
懒汉、饿汉
就单例而言,其实分为两种,一为懒汉模式,另一个是饿汉模式。就我们上面所写,其实就是懒汉模式,因为是需要的时候才去创建,不需要,就不去创建,是不是很懒啊。
那么饿汉模式怎么写呢:
public class MyFrame extends JFrame {
private static MyFrame f = new MyFrame();
private MyFrame() {
}
public static JFrame creatMyFrame() {
return f;
}
}
在声明的时候,直接进行实例化,这个就是饿汉模式,比喻是不是很形象,看着是不是很饥饿啊,哈哈。。。