多例模式

多例模式是相对单例模式而言的。单例模式有且仅有一个实例,但是多例模式,顾问思义:允许存在有限个实例。 什么叫“有限个实例”? 就是说:有多少实例,我们是知道的,并不是不可以预知的, 如果一个类的构造函数是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;
    }
}
多例模式1
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);
    }
    
    
}
多例模式2
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>
   
测试2

 

posted @ 2016-02-29 10:47  刘尊礼  阅读(180)  评论(0)    收藏  举报