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

来源:互联网 发布:centos鼠标键盘动不了 编辑:程序博客网 时间:2024/06/04 23:35
多例模式


1、多例模式是单例模式的推广,是对象的创建模式,其中多例类可以有多个实例,而且多例类必须自己创建、管理自己的实例,并向外界提供自己的实例。


2、多例模式特点:
1、多例类可以有多个实例;
2、多例类必须自己创建、管理自己的实例,并向外界提供自己的实例;


3、单例类和多例类的结构图:




单例类只有一个实例,但允许有限个实例。允许有限个实例向整个虚拟机提供自己的实例类,这样就成了多例类,


4、骰子的例子:


多例类骰子:


import java.util.Date;
import java.util.Random;


public class multitondie {


private static multitondie md1 = new multitondie();
private static multitondie md2 = new multitondie();


// 私有构造方法,外界无法直接实例化此类
private multitondie() {


}


// 工厂方法
public static multitondie getInstance(int which) {
if (which == 1) {
return md1;
} else {
return md2;
}


}


// 生产随机数
public synchronized int dice() {
Date d = new Date();
Random random = new Random(d.getTime());
int val = random.nextInt();
val = Math.abs(val);
val = val % 6;
val += 1;
return val;
}
}


客户端调用:
package client;


import multiton.multitondie;


public class multiondieclient {


private static multitondie md1, md2;


public static void main(String[] args) {


md1 = multitondie.getInstance(1);
md2 = multitondie.getInstance(2);
for (int i = 0; i < 3; i++) {
System.out.println(md1.dice());
System.out.println(md2.dice());
System.out.println("=================");
}


}
}


结果打印;
4
1
=================
1
1
=================
1
1
=================




在骰子的多例类中,使用了饿汉方式创建两个骰子的实例。工厂方法返回两个实例中的一个。


这是一个有上限的多例类,可以用静态变量存储所有的实例,特别当实例数目不多的时候,可以使用一个个的静态变量存储一个个的实例。当数目较多,就需要使用静态聚集存储这些实例。


实例数目没有上限的多例模式叫做无上限多例模式。


5、国际化的实例


多例类

import java.util.HashMap;
import java.util.Locale;
import java.util.ResourceBundle;


public class languageresource {


private String language = "en";
private String region = "US";
private String localCode = "en_US";
private static final String FILE_NAME = "res";
private static HashMap instance = new HashMap(19);
private Locale locale = null;
private ResourceBundle resourcebundle = null;
private languageresource languageresource;


// 私有构造方法外界无法直接实例化,所有实例通过调用getInstance得到
public languageresource(String language, String region) {
this.language = language;
this.region = region;
localCode = makeLocalCode(language, region);// en_US
locale = new Locale(language, region);
resourcebundle = ResourceBundle.getBundle(FILE_NAME, locale);
// 放到instance集合中
instance.put(localCode, resourcebundle);// res_en_US


}


// 私有构造方法外界无法直接实例化
public languageresource() {
// TODO Auto-generated constructor stub
}


// 工厂方法,返还一个实例,调用getInstance得到实例
public synchronized static languageresource getInstance(String language,
String region) {
/*
* 判断localCode代码是否存在instance中,存在直接返回它对应的languageresource对象
* 否则就会创建一个此local代码对应的languageresource,将之插入到instance集合中,返回这个实例。
*/
if (instance.containsKey(makeLocalCode(language, region))) {
return (languageresource) instance.get(makeLocalCode(language,
region));
} else {
return new languageresource(language, region);
}
}


public String getLoacleString(String code) {
return resourcebundle.getString(code);
}


// 返回localCode en_US
private static String makeLocalCode(String language2, String region2) {
return language2 + "_" + region2;
}


}

资源文件


res_en_US.properties
hello=Hello
world=World


res_zh_CH.properties
hello=\u4F60\u597D
world=\u4E16\u754C


客户端调用:
package client;


import multiton.languageresource;


public class languagetest {


public static void main(String[] args) {


languageresource lg = languageresource.getInstance("en", "US");
String ushello = lg.getLoacleString("hello");
String usworld = lg.getLoacleString("world");


System.out.println("美国打招呼" + ushello + usworld);


languageresource lgzh = languageresource.getInstance("zh", "CH");
String zhhello = lgzh.getLoacleString("hello");
String zhworld = lgzh.getLoacleString("world");


System.out.println("中国打招呼" + zhhello + zhworld);
}


}


结果输出:
美国打招呼HelloWorld
中国打招呼ä½ å¥½ä¸–ç


出现乱码原因以及抛出异常:
Exception in thread "main" java.util.MissingResourceException: Can't find bundle for base name res, locale en_US
抛出上面异常说明是资源文件路径放错了。要把资源文件放在src的同级目录。


运行后打印
美国打招呼HelloWorld
中国打招呼ä½ å¥½ä¸–ç


首先英文可以打印,排除路径问题,开始我以为是工作空间编码方式不对,可是更改后依然如此。
后来debug进去,一步步的跟下去,发现资源文件放进ResourceBundle.getBundle就是乱码的,所以判断一定和资源文件的编码方式,以及Java读取的方式有关。
经过一番查找资料,发现Java读取properties文件,只认识ASCII码,所以设置properties文件编码为ASCII码即可。
如是:
res_zh_CH.properties
ASCII码
hello=\u4F60\u597D //hello=你好的ASCII码
world=\u4E16\u754C //world=世界的ASCII码


打印输出:
美国打招呼HelloWorld

中国打招呼你好世界


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

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


原创粉丝点击