一.何为单例模式
单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。(选自维基百科)
通常单例模式在Java语言中,有两种构建方式:
懒汉方式。指全局的单例实例在第一次被使用时构建。
饿汉方式。指全局的单例实例在类装载时构建。
下面是自己对两种方式的优缺点辨析:懒汉方式由于是在使用时才创建示例,因为类加载较快,但是懒汉方式在多线程情况下不能使用(所以笔者的懒汉代码示例是变种懒汉),而饿汉方式则没有线程不安全的情况,在装载类时就创建实例,但是其效率较之于懒汉模式就比较低。
通常单例模式在Java语言中,有两种构建方式:
懒汉方式。指全局的单例实例在第一次被使用时构建。
饿汉方式。指全局的单例实例在类装载时构建。
下面是自己对两种方式的优缺点辨析:懒汉方式由于是在使用时才创建示例,因为类加载较快,但是懒汉方式在多线程情况下不能使用(所以笔者的懒汉代码示例是变种懒汉),而饿汉方式则没有线程不安全的情况,在装载类时就创建实例,但是其效率较之于懒汉模式就比较低。
二.为何用使用单例模式
1
.首先,只需要创建一个实例对象,占用内存较少。
2.能避免存在多个实例影响程序逻辑错误的场合。
三.代码示例(界面与 控制台两种视图模式)
下面是加双锁以确保线程安全的懒汉模式(同时也是MVC框架的Controller):
import javax.swing.JFrame;
public class Singleton {
private static volatile Singleton INSTANCE=null;
private Num NUM;
private Numview1 VIEW1;
private Numview2 VIEW2;
private int mode;//视图模式选择
private Singleton(){};
public static Singleton getinstance()
{
if(INSTANCE==null)
{
synchronized(Singleton.class)
{
if(INSTANCE==null)
INSTANCE=new Singleton();
}
}
return INSTANCE;
}
public void setMode(int i)//设置视图模式,1为界面,2为控制台
{
mode=i;
}
public void CreateNum(int num)
{
NUM=new Num(num);
}
public int getNum()
{
return NUM.getNum();
}
public String getAttribute()
{
return NUM.getAttribute();
}
public void Judge()
{
NUM.Judge();
}
public void ShowView()
{
switch(mode){
case 1:
{
VIEW1=new Numview1(this);
VIEW1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
VIEW1.setSize(450,120);
VIEW1.setVisible(true);
break;
}
case 2:
{
VIEW2=new Numview2(this);
VIEW2.show();
break;
}
default :System.out.println("设置视图模式错误");
}
}
}
普通饿汉模式(只写了改变和获取实例这部分即可,其他Controller部分与懒汉模式一样)
public class Singleton {
private static Singleton INSTANCE = new Singleton();//静态私有成员,已初始化
private static volatile Singleton INSTANCE=null;
private Num NUM;
private Numview1 VIEW1;
private Numview2 VIEW2; private int mode;//视图模式选择
private Singleton(){};
public static Singleton getinstance()//返回唯一实例
{
return INSTANCE;
}
}
下面是MVC的model,也就是数这个对象
public class Num {
private int num;
private String att;
public Num(int i)
{
num=i;
att=new String("这是一个数");
}
public void setNum(int i)
{
num=i;
}
public int getNum()
{
return num;
}
public String getAttribute()
{
return att;
}
public void Judge()
{
if(num%2==0)
att="这是一个偶数";
else
att="这是一个奇数";
}
}
View模块
视图模式1(界面)import java.awt.Container;
import javax.swing.JFrame;
import java.awt.FlowLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
public class Numview1 extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private Singleton CONTROL;
public Numview1(Singleton Con)
{
super("奇偶判断");
CONTROL=Con;
Container c=getContentPane();//创建面板
c.setLayout(new FlowLayout());
JTextField DisNum=new JTextField("数字:",8);
DisNum.setEditable(false);
JTextField Num=new JTextField(8);//用于输入数字
Num.setEditable(true);
JButton Judge=new JButton("判断");
JTextField Display=new JTextField(8); //显示判断结果
Display.setEditable(false);
c.add(DisNum);
c.add(Num);
c.add(Judge);
c.add(Display);
Judge.addMouseListener(new MouseListener(){
public void mouseClicked(MouseEvent e)
{
String _num=Num.getText();
CONTROL.CreateNum(Integer.parseInt(_num));
CONTROL.Judge();
Display.setText(Con.getAttribute());
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
});
}
}
视图模块2(控制台)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Numview2 {
private Singleton CONTROL;
public Numview2(Singleton Con){
CONTROL=Con;
}
public void show(){
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
String _num;
try
{
do{
_num=in.readLine();
if(Integer.parseInt(_num)!=-1)
{
CONTROL.CreateNum(Integer.parseInt(_num));//对对象进行相关处理
CONTROL.Judge();// 判断并设置属性
System.out.println(CONTROL.getAttribute());
}
}while(Integer.parseInt(_num)!=-1);
System.out.println("结束");
}
catch(IOException e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
四.结果
视图1(界面)视图2(控制台)
五.总结:
看了几篇关于单例模式的博客,对单例模式有了大概的了解,单线程用懒汉模式较好,如果在多线程的情况下,就需要通过加锁等方式来保证线程安全,饿汉模式的话虽然安全,但由于是一开始就创建了实例,可能造成内存浪费,然后就是如何将单例与MVC模式相结合,笔者会在后面的博客里再进行关于对MVC理解的探讨。由于是菜鸟一只,如有什么不对的地方,还请不吝赐教,请在评论下留言。