理系学生日記

おまえはいつまで学生気分なのか

Commons Collections で FizzBuzz

Java SE では、機能ロジックをカプセル化した関数オブジェクトとして例えば Comparator や Iterator が定義されていますが、Apache Commons collections には、for 文や while 文、if 文をカプセル化した Functor が用意されています。なるほど、これを使えば FizzBuzz 問題が解けるなということで、実際にやってみた。

[kiririmode@mbp(job:0)]% ant run
Buildfile: build.xml

run:
     [java] 1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizzbuzz 16 17 fizz 19 buzz fizz 22 23 fizz buzz 26 fizz 28 29 fizzbuzz 31 32 fizz 34 buzz fizz 37 38 fizz buzz 41 fizz 43 44 fizzbuzz 46 47 fizz 49 buzz fizz 52 53 fizz buzz 56 fizz 58 59 fizzbuzz 61 62 fizz 64 buzz fizz 67 68 fizz buzz 71 fizz 73 74 fizzbuzz 76 77 fizz 79 buzz fizz 82 83 fizz buzz 86 fizz 88 89 fizzbuzz 91 92 fizz 94 buzz fizz 97 98 fizz 

BUILD SUCCESSFUL
Total time: 0 seconds

つくりは非常に冗長なかんじになっていて、リファクタリングもまったくしてないけどぼくは元気ですし満足です。

package test.commons.fizzbuzz;

import test.commons.fizzbuzz.HundredIterator;
import org.apache.commons.collections.functors.WhileClosure;
import org.apache.commons.collections.Closure;
import org.apache.commons.collections.Predicate;

public class Main {
    private static FizzBuzzClosure fbc = new FizzBuzzClosure();
    public static void main(String[] args) {

        fizzbuzz();
    }

    private static void fizzbuzz() {
        
        Predicate p = new Predicate() {
                @Override public boolean evaluate( Object object ) {
                    HundredIterator itr = (HundredIterator)object;
                    return itr.hasNext();
                }

        };
        Closure c = new Closure() {
                @Override public void execute( Object input ) {
                    HundredIterator hitr = (HundredIterator)input;
                    fbc.execute( hitr.next() );
                }
        };
        new WhileClosure( p, c, true ).execute( new HundredIterator() );
    }
        
}
package test.commons.fizzbuzz;

import org.apache.commons.collections.functors.WhileClosure;
import org.apache.commons.collections.Closure;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.functors.AndPredicate;
import org.apache.commons.collections.functors.SwitchClosure;

public class FizzBuzzClosure implements Closure {

    private Predicate isFizz     = null;
    private Predicate isBuzz     = null;
    private Predicate isFizzBuzz = null;

    private Closure fizz           = null;
    private Closure buzz           = null;
    private Closure fizzbuzz       = null;
    private Closure defaultClosure = null;

    private SwitchClosure fizzbuzzClosure = null;

    public FizzBuzzClosure() {
        setupPredicates();
        setupClosures();

        Predicate[] predicates = new Predicate[] { isFizzBuzz, isFizz, isBuzz };
        Closure[]   closures   = new Closure[] { fizzbuzz, fizz, buzz };
        fizzbuzzClosure        = new SwitchClosure( predicates, closures, defaultClosure );
    }

    public void execute( Object arg0 ) {
        fizzbuzzClosure.execute( arg0 );
    }

    private void setupPredicates() {
        isFizz = new Predicate() {
                @Override public boolean evaluate( Object arg0 ) {
                    Integer i = (Integer)arg0;
                    return i % 3 == 0;
                }
        };
        isBuzz = new Predicate() {
                @Override public boolean evaluate( Object arg0 ) {
                    Integer i = (Integer)arg0;
                    return i % 5 == 0;
                }
        };
        isFizzBuzz = new AndPredicate( isFizz, isBuzz );
    }

    private void setupClosures() {
        fizz = new Closure() {
                @Override public void execute( Object input ) { System.out.print( "fizz " ); }
        };
        buzz = new Closure() {
                @Override public void execute( Object input ) { System.out.print( "buzz " ); }
        };
        fizzbuzz = new Closure() {
                @Override public void execute( Object input ) { System.out.print( "fizzbuzz " ); }
        };
        defaultClosure = new Closure() {
                @Override public void execute( Object input ) { System.out.print( input + " " ); }
        };
    }
}