实例探索Java模式之路——单例模式

来源:互联网 发布:辣鸡软件表情 编辑:程序博客网 时间:2024/06/05 06:50
单例模式


1、单例模式是对象的创建模式,单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。


2、单例模式特点:
1、某个类只有一个实例;
2、它必须自行创建这个实例
3、它必须自行向整个系统提供这个实例;


3、单例模式中的单例类被限定只有一个实例,但单例模式和单例类可以很容易推广到任意且有有限个实例的情况,这时候就变成了多例模式和多例类。


4、饿汉式单例


饿汉式单例类是Java语言里实现最简单的单例类。在类初始化时已经自行实例化了。

public class eagersingleton {
private static final eagersingleton m_instance = new eagersingleton();//初始化时已经自行实例化


// 私有默认构造方法
private eagersingleton() {


}


// 静态工厂方法
public static eagersingleton getInstance() {
return m_instance;
}
}


特点:

饿汉单例类在自己被加载时,静态变量m_instance就会被初始化,此时类的私有构造方法就会被调用,单例类的唯一实例就会被创建出来了。
即便加载器是静态的,被加载时仍会将自己实例化。
Java单例类一个重要特点是类的构造方法是私有的,从而避免外界利用构造方法直接创建任意多的实例。
此外,由于构造方法是私有的,所以此类不能被继承。
天生是线程安全的。
是比较符合Java语言本身。


5、懒汉式单例


懒汉式单例类的构造方法也是私有的。懒汉式单例类在第一次被引用时将自己实例化,如果加载器是静态的,那么懒汉式单例类被加载时不会将自己实例化。
只有当调用getInstance的时候,才回去初始化这个单例。


public class lazysingleton {
private static lazysingleton m_instance = null;


// 私有默认构造方法,外界无法直接实例化
private lazysingleton() {


}


// 静态工厂方法
synchronized public static lazysingleton getInstance() {
if (m_instance == null) {
m_instance = new lazysingleton();//初始化这个单例
}
return m_instance;
}
}


静态工厂方法使用了同步化,以处理多线程环境。
由于构造方法是私有的,所以此类不能被继承。


6、登记式单例


是为了克服饿汉单例类和懒汉单例类均不能被继承的缺点而设计的。


import java.util.HashMap;


public class regsingleton {
static private HashMap m_registryHashMap = new HashMap();
static {
regsingleton regsingleton = new regsingleton();
m_registryHashMap.put(regsingleton.getClass().getName(), regsingleton);
}


// 保护的构造方法,外界无法直接实例化
protected regsingleton() {


}


// 静态工厂方法
static public regsingleton getInstance(String name) {
if (name == null) {
name = "lazysingleton.regsingleton";
}
if (m_registryHashMap.get(name) == null) {
try {
m_registryHashMap.put(name, Class.forName(name).newInstance());
} catch (Exception e) {
System.out.println("error happened!");
}
}
return (regsingleton) m_registryHashMap.get(name);
}


private String about() {
return "hello world regsingleton";
}
}


它的子类需要父类的帮助才能实例化。登记式单例类子类由父类将子类实例化。



public class regsingletonchild extends regsingleton {


private regsingletonchild() {


}


/**
* 静态工厂方法
*/
static public regsingletonchild getInstance() {
return (regsingletonchild) regsingleton
.getInstance("lazysingleton.regsingletonchild");
}


private String about() {
return "hello world regsingletonchild";
}
}


7、单例使用场景


在一个系统要求一个类只有一个实例时才应当使用单例模式。


8、通过属性管理器例子深入理解;


读取属性文件的单例类,作为单例模式的适用例子。
Singleton.properties


键=值
node1.item=hello
node2.item=1
node3.item=2
node4.item=3
node5.item=4
node7.item=5
node8.item=6
node9.item=world!


属性是一种资源,应避免多于一个的对象读取,特别是存储属性,属性文件管理器应当是由一个单例模式负责。


ConfigManager类有一个静态工厂getInstance用于提供自己的实例。


以饿汉方式实现的这个类:

package configmanager;


import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;


public class ConfigManager {
// 属性文件全名
private static final String PFILE = System.getProperty("user.dir")
+ File.separator + "Singleton.properties";
private File m_file = null;
private long m_lastModiedTime = 0;
private Properties m_props = null;
// 存在的唯一的一个实例
private static ConfigManager m_instance = new ConfigManager();


// 私有构造方法,保证外界无法直接实例化
private ConfigManager() {
m_file = new File(PFILE);


m_lastModiedTime = m_file.lastModified();
if (m_lastModiedTime == 0) {
System.err.println(PFILE + "file does not exist!");
}
m_props = new Properties();
try {
m_props.load(new FileInputStream(PFILE));
} catch (Exception e) {
e.printStackTrace();
}


}


// 静态工厂返回ConfigManager类的单一实例
synchronized public static ConfigManager getInstance() {
return m_instance;


}


// 读取一个特定的属性项
final public Object getConfigItem(String name, Object defaultVal) {
long newTime = m_file.lastModified();
if (newTime == 0) {
if (m_lastModiedTime == 0) {
System.err.println(PFILE + "file does not exist!");
} else {
System.err.println(PFILE + "file was deleted!");
}
return defaultVal;


} else if (newTime > m_lastModiedTime) {
m_props.clear();
try {
m_props.load(new FileInputStream(PFILE));
} catch (Exception e) {
e.printStackTrace();
}
}
m_lastModiedTime = newTime;
Object val = m_props.getProperty(name);
if (val == null) {
return defaultVal;
} else {
return val;
}
}
}


调用:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class test {


public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
System.out.println("Type qiut to quit");
do {
System.out.println("Property item to read!");
String line = reader.readLine();
if (line.equals("quit")) {
break;
}
System.out.println(ConfigManager.getInstance().getConfigItem(line,
"Not found!"));
} while (true);
}
}




9、Java应用单例模式实例
Java的Runtime对象
Introspector类
Java.awt.Toolkit类


10、懒汉式单例例子:这个例子能更好的让我理解单例模式


public class lazysingleton {
String name = null;
private static lazysingleton m_instance = null;


// 私有默认构造方法,外界无法直接实例化
private lazysingleton() {


}


// 静态工厂方法
synchronized public static lazysingleton getInstance() {
if (m_instance == null) {
m_instance = new lazysingleton();
}
return m_instance;
}


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


public void printinfo() {
System.out.println("name is " + name);
}
}


普通的Java对象


package lazysingleton;


public class nosingleton {
String name = null;


public String getName() {
return name;
}


public nosingleton(String name) {
this.name = name;
}


public void setName(String name) {
this.name = name;
}


public void printinfo() {
System.out.println("name is " + name);
}
}


测试类:


package lazysingleton;


public class test {
public static void main(String[] args) {


// 调用单例模式
lazysingleton t1 = lazysingleton.getInstance();
t1.setName("hello");
lazysingleton t2 = lazysingleton.getInstance();
t2.setName("world");


// lazysingleton t3= new lazysingleton();//报错,私有默认构造方法,外界无法直接实例化


t1.printinfo();
t2.printinfo();


if (t1 == t2) {
System.out.println("创建的是同一个实例");
} else {
System.out.println("创建的不是同一个实例");
}


// 调用普通
nosingleton nls1 = new nosingleton("第一次实例化");


nosingleton nls2 = new nosingleton("第二次实例化");


nls1.printinfo();
nls2.printinfo();


if (nls1 == nls2) {
System.out.println("创建的是同一个实例");
} else {
System.out.println("创建的不是同一个实例");
}
}
}


输出结果:
name is world
name is world
创建的是同一个实例
name is 第一次实例化
name is 第二次实例化

创建的不是同一个实例


通过此实例,相信对该模式有了进一步的认识。

每天努力一点,每天都在进步。



0 0