单件模式是关于怎样设计一个类,并使得该类只有一个实例的成熟模式,该模式的关键是将类的构造方法设置为private权限,并提供一个返回它的唯一实例的类方法。
在某些情况下,我们可能需要某个类只能创建出一个对象,即不让用户用该类实例化出多于两个的实例。
例如:在一个公文管理系统中,公文类的实例“公文文件”,需要将公章类的实例作为自己的一个成员,且公章类只有一个实例。
优点:单件类的唯一实例由单件类本身来控制,所以可以很好地控制用户何时访问它。
角色:
单件类(Singleton):单件类只可以创建出一个实例
单件类(Singleton)的UML图
单件类在设计上的特点:
设计单件类的两种方法:
1.在JVM加载单件类时创建它的唯一实例
对于单件类中声明的类变量,即该单件类的唯一实例,在单件类被JVM加载到内存时就会被分配空间,该内存空间用于存放该实例的引用,因此,可以在声明类变量的同时就初始化它,即创建该实例。
public class Singleton{
private static Singleton uniqueInstance=new Singleton();
//JVM 加载Singleton时创建uniqueInstance
private Singleton(){ } //构造方法是private权限
public static Singleton getInstance(){ //返回唯一实例的类方法
return uniqueInstance;
}
}
2.在单件类提供的类方法中创建这个唯一实例
如果程序希望用户需要时再创建单件类的唯一实例,即用户调用单件类提供的类方法时再创建它,那么为了防止多线程在调用这个类方法时创建多个单件类的实例,可以将类方法设置为同步方法。
public class Singleton{
private static Singleton uniqueInstance;
private Singleton( ) { } //构造方法是private权限
public static synchronized Singleton getInstance( ) {
if (uniqueInstance==null){
uniqueInstance=new Singleton( );
}
return uniqueInstance;
}
}
实例:
创建唯一的月亮。单件模式的类图是所有模式中最简练的,只涉及一个角色:单件类。
该实例的UML图:
Moon.java
在JVM加载单类时创建的Moon.Java
public class Moon{
private static Moon uniqueMoon=new Moon();
double radius=1738;
double distanceToEarth=363300;
private Moon(){}
public static synchronized Moon getMoon(){
return uniqueMoon;
}
public String show(){
String s="月亮的半径是"+radius+"km,距地球是"+distanceToEarth+"km";
return s;
}
}
在单间类提供的类方法中创建的Moon.Java
public class Moon{
private static Moon uniqueMoon;
double radius;
double distanceToEarth;
private Moon(){
uniqueMoon=this;
radius=1738;
distanceToEarth=363300;
}
public static synchronized Moon getMoon(){
if(uniqueMoon==null){
uniqueMoon=new Moon();
}
return uniqueMoon;
}
public String show(){
String s="月亮的半径是"+radius+"km,距地球是"+distanceToEarth+"km";
return s;
}
}
应用程序
import javax.swing.*;
import java.awt.*;
public class Application{
public static void main(String args[]){
MyFrame f1=new MyFrame("张三看月亮");
MyFrame f2=new MyFrame( "李四看月亮");
f1.setBounds(100,100,760,550);
f2.setBounds(370,100,760,550);
f1.validate();
f2.validate();
}
}
class MyFrame extends JFrame{
String str;
MyFrame(String title){
setTitle(title);
Moon moon=Moon.getMoon();
str=moon.show();
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setVisible(true);
repaint();
}
public void paint(Graphics g){
super.paint(g);
g.setFont(new Font("黑体",Font.BOLD,34));
g.drawString(str,5,100);}
}
运行结果:
单件类的唯一实例由单件类本身来控制,所以可以很好地控制用户何时访问它。
这里是不吃香菜也可做香菜头子。