多例模式
多例模式是相对单例模式而言的。单例模式有且仅有一个实例,但是多例模式,顾问思义:允许存在有限个实例。 什么叫“有限个实例”? 就是说:有多少实例,我们是知道的,并不是不可以预知的, 如果一个类的构造函数是public 的,那么在任意地方都可以通过调用构造函数来创建实例,那么这样的实例是我们不能预知的。这是有上限多例模式,但是多例模式还有一种无上限多例模式。因此,多例模式有以下特点:
- 允许有多个实例
- 多例类自己负责创建、管理自己的实例、并向外界提供自己的实例。因此,他的构造函数也是private的,这点跟单例模式是相同的。
多例模式分为两种:
1.有限个实例
2.有多少个实例,不知道,但对实例有所控制
1.有限个实例:这个很好理解,有多个实例,但是确定个数,不能再多
比如玩麻将,只有2个骰子,不可能有多个,所以只生成2个实例就可以了
思路:new两个实例,怎么做呢,getInstance的时候,判断情况,只返回这两个实例就可以了,同样的要构造函数私有

package com.pattern.multilingual; import java.util.Date; import java.util.Random; public class Die { /** * 创建2个实例 */ private static Die die1 = new Die(); private static Die die2 = new Die(); /** * 私有构造子 */ private Die() { } /** * 工厂方法 * @param whichOne * @return */ public static Die getInstance(int whichOne) { if (whichOne == 1) { return die1; } return die2; } /** * 掷骰子 * @return */ public synchronized int dice(){ Date d = new Date(); Random r = new Random(d.getTime()); int value = r.nextInt(); value = Math.abs(value)%6+1; return value; } }

package com.pattern.multilingual; public class Client { private static Die die1,die2; public static void main(String[] args) throws InterruptedException{ die1 = Die.getInstance(1); die2 = Die.getInstance(2); System.out.println(die1.dice()); Thread.sleep(2000); System.out.println(die2.dice()); } }
2.无限个实例,不知道有多少个实例,那为什么还搞个多例设计模式呢,多例设计模式的意义是什么呢?
多例模式的意义就是,自己可以控制生成实例,即使是不知道有多少个,也可以控制。
思路:1.构造函数私有,getInstance怎么控制生成的实例呢,答案是加一个List,怎么加?
2.getInstance判断,如果是List里有这个对象,返回List里的,如果没有生成新的对象

package com.pattern.multilingual; import java.util.HashMap; import java.util.Locale; import java.util.ResourceBundle; public class LingualResource { private String localeCode = "en_US"; private static final String FILE_NAME = "test"; private static HashMap<String,LingualResource> instances = new HashMap<String,LingualResource>(19); private Locale locale = null; private ResourceBundle bundle = null; /** * 构建LocaleCode * @param language * @param region * @return */ private static String makeLocaleCode(String language,String region){ return new StringBuilder(language).append("_").append(region.toUpperCase()).toString(); } /** * 构造子 * @param language * @param region */ private LingualResource(String language,String region){ localeCode = makeLocaleCode(language,region); this.locale = new Locale(language,region); bundle =ResourceBundle.getBundle(FILE_NAME,locale); instances.put(localeCode, this); } private LingualResource(){} /** * 工厂方法 * @param language * @param region * @return */ public synchronized static LingualResource getInstance(String language,String region){ if(instances.get(makeLocaleCode(language,region)) != null){ return instances.get(makeLocaleCode(language,region)); } return new LingualResource(language,region); } /** * 国际化方法 * @param code * @return */ public String getLocaleString(String code){ return this.bundle.getString(code); } }

package com.pattern.multilingual; public class ResourceTest { public static void main(String[] args){ LingualResource ling = LingualResource.getInstance("en", "US"); String usName = ling.getLocaleString("name"); LingualResource lingCN = LingualResource.getInstance("zh","CN"); String cnName = lingCN.getLocaleString("name"); System.out.println("usName:" + usName); System.out.println("cnName:" + cnName); } } 资源文件: <pre name="code" class="plain">test_en_US.properties name=john age=20 test_zh_CN.protites name=\u7EA6\u7FF0 age=20</pre><br> <br> 指印结果如下:<br> <pre name="code" class="css">usName:john cnName:约翰 </pre><br> 其实在我们的开发中,其实很少这样写,通常像这种情况,可能在我们需要国际化的地方直接 new()的方式创建实例,相比之下采用这种方式,可以减少内存开支,省去了反复创建对象和回收对象的麻烦。<br> <br> <span style="font-size:18px; color:#FF0000">ps:在《JAVA与模式》一书中260页,这个国际化的例子,有错误,比如他的工厂方法是错误,而且存在大量的多余变量,部分问题考虑的很是不周到,有兴趣的朋友可以自己翻书对照一下,我的代码与书的代码。</span><br> <span style="font-size:18px; color:#FF0000">同时,发现在本书中存在大量的错误,不知道是笔者手误,还是印刷出版社的印刷错误,希望大家在看此书时,抱着审视的态度。“尽信书则不如无书”,不过此书的例子仍然非常棒,这仍然是一本不错的书籍。</span><br> <pre></pre> <p></p> <pre></pre> <p></p> <p><br> </p> <p>ps:多例模式,这个多例包括1个实例,因此多例模式是单例模式的推广,单例模式是多例模式的特例,另外给大家科普点小知识,为什么国际化(Internationalization)简称i18N? 那是因为I和n之间有18个字母,挺逗的命名。<br> </p> <p><br> </p> <p><br> </p> <p><br> <br> </p>