2011年12月30日金曜日

Chain Of ResponsibilityパターンによるFizzBuzz実装

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
出落ち感満載ですが、実装してみました。
単純にGoFデザインパターンの一つであるChain Of Responsibilityパターンを使ってみたかっただけです。
今まで実際に使った事が無かったので・・・。

Chain Of Responsibilityパターンって?


ggrks。
Wikipedia:Chain of Responsibility パターン
簡単に言うと責任の鎖。「ちょっと責任者に代わって。君じゃ埒があかん。」とこういう事ですね。


実装


ChainOfResponsibilityクラスのインナークラスとして全て書いています。
Fizz, Buzz, FizzBuzz, Integersクラスは抽象クラスであるHandlerを継承しています。
ChainOfResponsibility#fizzBuzz()の中でsetNextしてお互いを連結しています。

Handler#fizzBuzz(int)で実行。inCharge(int)で自分がこの値を担当しているかどうかをbooleanで返します。担当であればpring(int)を実行して終了。担当じゃなかったら自分の次の人のHandler#fizzBuzz(int)を呼び出します。

例えば65という値が入れられた場合はFizzBuzz->Fizz->Buzzまで行ってprintされます。

なんとなくFizzBuzzクラスやIntegersクラスのinCharge(int)はFizzクラスとBuzzクラスを使って判定させてます。
連結の仕方によって計算量が変わる気がしますがなんだか面倒なので考えるのをやめました。
もっと短く出来ると思いますが面倒なので(ry

public class ChainOfResponsibility {
    static public abstract class Handler{
        private Handler next = null;
       
        public Handler setNext(Handler next){
            this.next = next;
            return next;
        }
        public final void fizzBuzz(int value){
            if(inCharge(value)){
                print(value);
            }else if(next != null){
                next.fizzBuzz(value);
            }else{
                throw new RuntimeException("Oops!");
            }
        }
        protected abstract boolean inCharge(int value);
        protected abstract void print(int value);
    }
    
    static class Integers extends Handler{
        Fizz fizz = new Fizz();
        Buzz buzz = new Buzz();
        @Override
        protected boolean inCharge(int value) {
            return !fizz.inCharge(value) && !buzz.inCharge(value);
        }
        @Override
        protected void print(int value) {
            System.out.println(value);
        }
    }
    static class Fizz extends Handler{
        @Override
        protected boolean inCharge(int value) {
            return value%3 == 0;
        }
        @Override
        protected void print(int value) {
            System.out.println("Fizz");
        }
    }
    static class Buzz extends Handler{
        @Override
        protected boolean inCharge(int value) {
            return value%5 == 0;
        }
        @Override
        protected void print(int value) {
            System.out.println("Buzz");
        }
    }
    
    static class FizzBuzz extends Handler{
        Fizz fizz = new Fizz();
        Buzz buzz = new Buzz();
        @Override
        protected boolean inCharge(int value) {
            return fizz.inCharge(value) && buzz.inCharge(value); 
        }
        @Override
        protected void print(int value) {
            System.out.println("FizzBuzz");
        }
    }
    
    public void fizzBuzz(){
        Handler integer = new Integers();
        Handler fizz = new Fizz();
        Handler buzz = new Buzz();
        Handler fizzBuzz = new FizzBuzz();
        
        fizzBuzz.setNext(fizz).setNext(buzz).setNext(integer);
        for(int i = 1; i <= 100; i++){
            fizzBuzz.fizzBuzz(i);
        }
    }
    
    public static void main(String[] args) {
        new ChainOfResponsibility().fizzBuzz();
    }
}

まとめ


このパターンはいろいろ使えそうだなぁ。
デザインパターンによるFizzBuzz実装をシリーズ化できるかなー。どうかな。

0 件のコメント:

コメントを投稿