Itsukaraの日記

最新IT技術を勉強・実践中。最近はDeep Learningに注力。

Javaのシングルトンの使い方を例題で確認しました

Javaのシングルトンについて知りたかったのでJavaでSingletonパターンを実装するのにclassとenumのどちらを使うべきか - SELECT * FROM life;を読ませて頂きました。しかし、シングルトンの定義しか書いていないため、使い方が今一つ分かりませんでした。そこで、例題を作って確かめてみました。下記で、シングルトンの使い方を2つ書きましたが、2つ目は、enum型の要素に対して直接メソッドを呼び出すので、かなり不自然に感じました。(実際は1つめも同じではありますが...)

import java.util.Arrays;
import java.util.List;

// 下記はテスト用の補助的なクラスです
class StringList {
    List<String> stringList;
    public StringList(String... strings) {
    	stringList = Arrays.asList(strings);
//        stringList = new LinkedList<>();
//        for (String string: strings) {
//            stringList.add(string);
//        }
    }
    public List<String> getStringList() {
        return stringList;
    }
}

// シングルトンクラスです
enum RichestPerson {
    INSTANCE;
    private String name = "Bill Gates";
    // フィールドの初期時値は実行時に設定することも可能
    private StringList favoriteFruits = new StringList("Orange", "Strawberry", "'Every fruits except Apple'");
    private StringList favoriteDrinks = new StringList("Coke", "Coffee", "Wine");
    public String getName() {
        return name;
    }
    public List<String> getFavoriteFruits() {
        return favoriteFruits.getStringList();
    }
    public List<String> getFavoriteDrinks() {
        return favoriteDrinks.getStringList();
    }
    public void changePerson(String name, StringList favoriteFruits, StringList favoriteDrinks) {
        this.name = name;
        this.favoriteFruits = favoriteFruits;
        this.favoriteDrinks = favoriteDrinks;
    }
}

/* error: enum types are not extensible
class test extends RichestPerson { }
*/

// テスト実施クラス
public class SingletonTest {
    public static void main(String[] args) {
        SingletonTest singletonTest = new SingletonTest();
        singletonTest.test();
    }
    public void test() {
        /* error: enum types may not be instantiated
        RichestPerson theOne = new RichestPerson();
        */
        /* error: non-static method getName() cannot be referenced from a static context
        String theName = RichestPerson.getName();
        */

        // 下記は、自然な使い方
        RichestPerson theOne = RichestPerson.INSTANCE;
        // 下記も、これだけ見ると、あまり不自然に見えない
        System.out.print("Favorite Fruits of "+theOne.getName()+":");
        List<String> favoriteFruitsOfRichestPerson = theOne.getFavoriteFruits();
        for (String fruit: favoriteFruitsOfRichestPerson) {
            System.out.print(" "+fruit);
        }
        System.out.println("");

        // 下記はenum型の要素に対してメソッドを呼び出すので、なんか不自然な感じ
        System.out.print("Favorite Fruits of "+RichestPerson.INSTANCE.getName()+":");
        List<String> favoriteDrinksOfRichestPerson = RichestPerson.INSTANCE.getFavoriteDrinks();
        for (String drink: favoriteDrinksOfRichestPerson) {
            System.out.print(" "+drink);
        }
        System.out.println("");
    }
}

/* 実行結果:
Favorite Fruits of Bill Gates: Orange Strawberry 'Every fruits except Apple'
Favorite Fruits of Bill Gates: Coke Coffee Wine
*/