Java设计模式 - 单例模式
单例模式使用场景:
单例模式保证仅有一个实例,并提供一个访问它的全局访问点.当系统需要某个类只能有一个实例时,就可以采用单例模式.
源码下载地址:
https://github.com/godlikecheng/singleton_model
单例模式的实现方式:
1.直接实例化
package singleton_model;
/**
* 单例模式 - 直接实例化
* @author 张宜成
*/
public class Singleton_01 {
// 构造方法私有化
private Singleton_01 () {
}
// 直接产生单例模式
private static final Singleton_01 single = new Singleton_01();
public static Singleton_01 getinstance () {
return single;
}
}
2.延迟实例化
package singleton_model;
/**
* 单例模式 - 延迟实例化
* @author 张宜成
*/
public class Singleton_02 {
// 构造方法私有化
private Singleton_02 () {
}
private static Singleton_02 single = null;
/*
* 本方法是通过双重锁部分同步机制获得单例对象的.
* 因为代码中有两行相同的语句if(single == null),故叫做双重锁.
*/
public static Singleton_02 getInstance () {
if (single == null) {
synchronized (Singleton_02.class) {
if (single == null) {
single = new Singleton_02();
}
}
}
return single;
}
}
3.静态内部类
package singleton_model;
/**
* 单例模式 - 静态内部类 -> 利用静态内部类生成的单例对象时更优的
* @author 张宜成
*/
public class Singleton_03 {
// 静态内部类
private static class My {
private static final Singleton_03 single = new Singleton_03();
}
private Singleton_03 () {
System.err.println("This is new instance!!!"); // 做测试使用
}
public static final Singleton_03 getInstance () {
return My.single;
}
}
静态内部类 - 测试类:
package singleton_model;
/**
* 单例模式 - 静态内部类 -> 利用静态内部类生成的单例对象时更优的
* @author 张宜成
*/
public class Singleton_03 {
// 静态内部类
private static class My {
private static final Singleton_03 single = new Singleton_03();
}
private Singleton_03 () {
System.err.println("This is new instance!!!"); // 做测试使用
}
public static final Singleton_03 getInstance () {
return My.single;
}
}
运行效果:
应用案例:
1.编制日志类.一般来说,应用程序都有日志文件,记录一些执行信息,该功能利用单例对象来实现是比较恰当的.本案例实现最基本的功能,包括:记录时间及相关内容字符串,其代码如下所示.
package singleton_model;
import java.io.*;
import java.util.*;
/**
* 编制日志类,一般来说,应用程序都有日志文件,记录一些执行信息,该功能利用单例对象来实现是比较恰当的.
* 本例实现最基本的功能,包括:记录时间及相关内容字符串.
* @author 张宜成
*/
public class FileLogger {
private String path = "f:/";
private FileOutputStream out;
private FileLogger() throws Exception {
System.out.println("This is new instance !");
}
// 公有写入方法,供测试类调用
public void write(String msg) {
try {
Calendar c = Calendar.getInstance();
int y = c.get(Calendar.YEAR);
int m = c.get(Calendar.MONTH);
int d = c.get(Calendar.DAY_OF_MONTH);
int hh = c.get(Calendar.HOUR);
int mm = c.get(Calendar.MINUTE);
int ss = c.get(Calendar.SECOND);
String strTime = "";
// strTime = strTime.format("time:%d-%02d-%02d %02d:%02d:%02d\r\n", y,m,d,hh,mm,ss);
String strContent = "content:\r\n" + msg + "\r\n";
byte buf[] = strTime.getBytes("gbk");
out.write(buf);
out.flush();
}catch(Exception e) {
e.printStackTrace();
}
}
// 公有关闭方法,供测试类使用
public void close() {
try {
out.close();
}catch(Exception e) {
e.printStackTrace();
}
}
// 静态内部类
/*
* 按照
* private static FileLogger getInstance(){
* private static final FileLogger log = new FileLogger();
* }
* 是错误的,他需要处理流的异常,用try..catch代码块来处理
*/
private static class My {
static FileLogger log;
static {
try {
log = new FileLogger();
}catch(Exception e) {
e.printStackTrace();
}
}
}
// 提供访问内部类的公有方法
public static FileLogger getInstance(){
return My.log;
}
}
日志类 - 测试类
package singleton_model;
/**
* 一个简单的应用该日志类的测试代码如下所示.
* @author 张宜成
*/
public class FileLogger_Test {
public static void main(String[] args) {
FileLogger obj = FileLogger.getInstance(); // 获得日志 的单例对象
obj.write("hello");
obj.write("你好!");
obj.close();
}
}
2.编制配置文件信息单例模式 配置文件是应用程序经常采用的技术,它的内容为整个应用程序所共享,具有唯一性,因此利用单例对象来读取配置文件是可取的.假设关于数据库文件的信息图下如,并存放到f:/config.txt
url=jdbc:mysql://localhost:3306/mydb
username=root
password=123456
读取配置文件单例类代码如下所示.
package singleton_model;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* 单例模式 - 编制配置文件文件信息单例信息类
*
* @author 张宜成
*/
public class MyConfig {
private static Map<String, String> map = new HashMap(); // 保持配置文件键值对
private MyConfig() {
try {
FileInputStream in = new FileInputStream("f:/config.txt");
Properties p = new Properties();
p.load(in);
Set<Object> keys = p.keySet();
Iterator it = keys.iterator();
while (it.hasNext()) {
String key = (String) it.next();
String value = p.getProperty(key);
map.put(key, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static class My {
private static final MyConfig single = new MyConfig();
}
public static MyConfig getInstance () {
return My.single;
}
public String getInfo(String key) {
return map.get(key);
}
}
读取配置文件单例类 - 测试类
package singleton_model;
/**
* 单例模式 - 读取配置文件信息案例 - 测试类
* @author 张宜成
*/
public class MyConfig_Test {
public static void main(String[] args) {
MyConfig mc = MyConfig.getInstance(); // 获得单例对象
String url = mc.getInfo("url"); // 获取数据库的连接
String user = mc.getInfo("username"); // 获取用户名
String pwd = mc.getInfo("password"); // 获取密码
System.out.println("url = " + url);
System.out.println("user = " + user);
System.out.println("pwd = " + pwd);
}
}
运行效果: 将config.txt文件中的数据读取到了控制台
3.应用服务器单例技术仿真. 本示例利用java应用程序首先简单的仿真这一过程,即根据URL查找出对应的name值,再根据name值获得相应的运行类.具体功能是可激素那两个整数的加或减结果.所需要的代码如下所示.
定义接口IFunc
package singleton_model;
/**
* 单例模式 - 应用服务器单例技术仿真
* 本案例利用java应用程序首先简单的仿真这一过程,即根据URL查找出对应的name值,
* 再根据name值获得响应的运行类.具体功能是可计算证书的加或减结果.
* @author 张宜成
*/
public interface IFunc {
public int service(int one,int two);
}
定义功能类PlusFunc
package singleton_model;
/**
* 单例模式 - 应用服务器单例技术仿真
* @author 张宜成
*/
public class PlusFunc implements IFunc {
// 定义无参构造方法
private PlusFunc(){
}
// 定义匿名类
private static class My {
private static final PlusFunc single = new PlusFunc();
}
// 定义公有方法,让调用内部类中的方法
public static PlusFunc getInstance () {
// 调用内部类的方法,可以直接使用类名.方法名而无需实例化
return My.single;
}
// 实现接口中的方法 实现两个数的相加
public int service(int one, int two) {
return one + two;
}
}
定义功能类 MinusFunc
package singleton_model;
/**
* 单例模式 - 应用服务器单例技术仿真
* 本案例利用java应用程序首先简单的仿真这一过程,即根据URL查找出对应的name值,
* 再根据name值获得响应的运行类.具体功能是可计算证书的加或减结果.
* @author 张宜成
*/
public class PlusFunc implements IFunc {
// 定义无参构造方法
private PlusFunc(){
}
// 定义匿名类
private static class My {
private static final PlusFunc single = new PlusFunc();
}
// 定义公有方法,让调用内部类中的方法
public static PlusFunc getInstance () {
// 调用内部类的方法,可以直接使用类名.方法名而无需实例化
return My.single;
}
// 实现接口中的方法 实现两个数的相加
public int service(int one, int two) {
return one + two;
}
}
测试类
package singleton_model;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/**
* 单例模式 - 应用服务器单例技术仿真 - 测试类
* @author 张宜成
*/
public class IFunc_Test {
public static void main(String[] args) {
IFunc obj = PlusFunc.getInstance(); // 获得加单例对象
IFunc obj2 = MinusFunc.getInstance(); // 获得减单例对象
Map<String,Object> mapNameToObj = new HashMap();
mapNameToObj.put("plus", obj); // 将单例对象加入map映射中
mapNameToObj.put("minus", obj2); // name与类关联
Map<String,String> mapURLToName = new HashMap();
mapURLToName.put("plusurl", "plus"); // URL与name关联
mapURLToName.put("minusurl", "minus");
Scanner s = new Scanner(System.in);
while(true) {
String url = s.nextLine(); // 输入url,形如:plusurl 3 5
String unit[] = url.split(" ");
String name = mapURLToName.get(unit[0]);
IFunc iobj = (IFunc)mapNameToObj.get(name);
int result = iobj.service(Integer.parseInt(unit[1]), Integer.parseInt(unit[2]));
System.out.println("result is :" + result);
}
}
}
运行结果
下一篇: Java设计模式之 工厂模式