マイペースなプログラミング日記 このページをアンテナに追加 RSSフィード Twitter

カレンダー
<< 2009/03 >>
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

2009-03-17

[]Re:Java, デザインパターン: Simple Factory

http://www.yukun.info/blog/2009/03/java-design-pattern-simple-factory.html

このプログラムをちょっといじってみた。やったことはパターンが増える度にelse ifが増えてしまうことの解消と、思わぬ文字列が来てしまったときの対処(NullNamer)。結局、パターンが増えてしまえばそれだけaddPatternを呼び出さないといけないのは、仕方ないか。そして正規表現なんて使ってしまってるけど、区切り文字だけを渡せばすむ話だったと今気づく。あと1つのif文を消すためにクラス(NullNamer)を増やしてしまったのも考え物かも。以下ソース

public class Main{
    public static void main(String[] args){
        NameFactory nameFactory = new NameFactory();
        Namer namer;

        namer = nameFactory.getNamer("String#indexOf");
        printName(namer);
        namer = nameFactory.getNamer("ArrayList.get()");
        printName(namer);
        namer = nameFactory.getNamer("Thread#run");
        printName(namer);
        namer = nameFactory.getNamer("NULL");
        printName(namer);
    }

    private static void printName(Namer namer){
        System.out.println("Class Name:" + namer.getClassName());
        System.out.println("Method Name:" + namer.getMethodName());
    }
}
import java.util.Map;
import java.util.HashMap;
import java.util.regex.Pattern;

public class NameFactory{
    private final Map<Pattern, Namer> namerMap;
    private static final NullNamer NULL_NAMER = new NullNamer("null", "null");

    public NameFactory(){
        namerMap = new HashMap<Pattern, Namer>();

        addPattern(".+#.+", new SharpNamer());
        addPattern(".+\\..+", new PeriodNamer());
    }

    private void addPattern(String strPattern, Namer namer){
        addPattern(Pattern.compile(strPattern), namer);
    }

    private void addPattern(Pattern pattern, Namer namer){
        namerMap.put(pattern, namer);
    }

    public Namer getNamer(String input){
        for(Pattern pattern : namerMap.keySet()){
            if(pattern.matcher(input).matches()){
                Namer namer = namerMap.get(pattern);
                namer.setInput(input);
                return namer;
            }
        }

        return NULL_NAMER;
    }
}
public abstract class Namer{
    protected String className;
    protected String methodName;

    public final String getClassName(){
        return className;
    }

    public final String getMethodName(){
        return methodName;
    }

    public abstract void setInput(String input);
}
public class NullNamer extends Namer{
    public NullNamer(String className, String methodName){
        this.className = className;
        this.methodName = methodName;
    }

    @Override
    public void setInput(String input){}
}
public class PeriodNamer extends Namer{
    // 「.」で名前を区切る
    @Override
    public void setInput(String str){
        int index = str.lastIndexOf(".");

        //すでに正規表現でチェック済みなのでif文はいらない
        className = str.substring(0, index);
        methodName = str.substring(index + 1);
    }
}
public class SharpNamer extends Namer{
    // 「#」で名前を区切る
    @Override
    public void setInput(String str){
        int index = str.lastIndexOf("#");

        //すでに正規表現でチェック済みなのでif文はいらない
        className = str.substring(0, index);
        methodName = str.substring(index + 1);
    }
}

yukunyukun 2009/03/17 21:19 トラバありがとうございます。私は最初if分を消すためにStateパターンで、区切り文字の違いを状態の違いと捉えようとしたのですが、それでも状態の数(区切り文字の数)分のクラスが必要になるので、このサンプルプログラムに対するパターンの適応が悪かったかと考えました。

正規表現やString#matchesを用いた解決法の提示、ありがとうございます。私もこの程度の粒度の問題に対しては、それがベターな選択肢だと思います。

d-kamid-kami 2009/03/17 22:55 状態数分のクラスを作るのは大変な作業だね。確かに、この程度ならクラスを増やすほどじゃないかも

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/d-kami/20090317/1237245091