Java
tips
簡単

簡易的な状態を管理するときに使うTIPS

More than 1 year has passed since last update.

概要

実装してるとき、今の状態と一つ前の状態を比べたり調べたりしたいときがたまーにありませんか?
今回はそんなときに使えるTIPSを紹介します。

詳細

ソースは以下。コピペで実行すれば動くはず。

SimpleGeneration.java
public class SimpleGeneration {
    public static void main(String[] args) {
        Status status = new Status();

        status.setStatus(Status.STATE_WAIT);
        System.out.println("status.setStatus(Status.STATE_WAIT);");
        System.out.println("-currentIs STATE_WAIT:" + status.currentIs(Status.STATE_WAIT));
        System.out.println("-beforeIs STATE_NONE:" + status.beforeIs(Status.STATE_NONE));
        System.out.println("");

        status.setStatus(Status.STATE_PROCESSING);
        System.out.println("status.setStatus(Status.STATE_PROCESSING);");
        System.out.println("-currentIs STATE_PROCESSING:" + status.currentIs(Status.STATE_PROCESSING));
        System.out.println("-beforeIs STATE_WAIT:" + status.beforeIs(Status.STATE_WAIT));
        System.out.println("");

        status.setStatus(Status.STATE_NONE);
        System.out.println("status.setStatus(Status.STATE_NONE);");
        System.out.println("-currentIs STATE_NONE:" + status.currentIs(Status.STATE_NONE));
        System.out.println("-beforeIs STATE_PROCESSING:" + status.beforeIs(Status.STATE_PROCESSING));
    }

    /**
     * 簡易的な世代管理機能を提供するインターフェース.
     */
    interface SimpleGenerationManageable {
        /**
         * 現在の状態を返す.
         * @return 現在の状態.
         */
        int getCurrent();


        /**
         * ひとつ前の状態を返す.
         * @return 一つ目の状態.
         */
        int getBefore();

        /**
         * 現在の状態を調べる.
         * @param current 調べたい状態
         * @return 調べたい状態と同じ場合、true.
         */
        boolean currentIs(int current);

        /**
         * ひとつ前の状態を調べる.
         * @param before 調べたい状態
         * @return ひとつ前の状態が調べたい状態と同じ場合、true.
         */
        boolean beforeIs(int before);
    }

    /**
     * ステータスクラス.
     * <p>現在の状態と一つ前の状態を保持する。</p>
     */
    public static class Status implements SimpleGenerationManageable {
        /** 状態:未処理. */
        public static final int STATE_NONE = 0;
        /** 状態:待ち. */
        public static final int STATE_WAIT = 1;
        /** 状態:処理中. */
        public static final int STATE_PROCESSING = 2;

        /** 現在の状態. */
        private int mCurrent = STATE_NONE;
        /** ひとつ前の状態. */
        private int mBefore = STATE_NONE;

        /**
         * 状態をセットする.
         * @param state セットする状態.
         */
        void setStatus(int state) {
            mBefore = mCurrent;
            mCurrent = state;
        }

        @Override
        public int getCurrent() {
            return mCurrent;
        }

        @Override
        public int getBefore() {
            return mBefore;
        }

        @Override
        public boolean currentIs(int current) {
            return mCurrent == current;
        }

        @Override
        public boolean beforeIs(int before) {
            return mBefore == before;
        }
    }
}

実行結果。

status.setStatus(Status.STATE_WAIT);
-currentIs STATE_WAIT:true
-beforeIs STATE_NONE:true

status.setStatus(Status.STATE_PROCESSING);
-currentIs STATE_PROCESSING:true
-beforeIs STATE_WAIT:true

status.setStatus(Status.STATE_NONE);
-currentIs STATE_NONE:true
-beforeIs STATE_PROCESSING:true

解説

SimpleGenerationManageable.java
    /**
     * 簡易的な世代管理機能を提供するインターフェース.
     */
    interface SimpleGenerationManageable {
        /**
         * 現在の状態を返す.
         * @return 現在の状態.
         */
        int getCurrent();


        /**
         * ひとつ前の状態を返す.
         * @return 一つ目の状態.
         */
        int getBefore();

        /**
         * 現在の状態を調べる.
         * @param current 調べたい状態
         * @return 調べたい状態と同じ場合、true.
         */
        boolean currentIs(int current);

        /**
         * ひとつ前の状態を調べる.
         * @param before 調べたい状態
         * @return ひとつ前の状態が調べたい状態と同じ場合、true.
         */
        boolean beforeIs(int before);
    }

簡易的な世代管理機能を提供するときに利用するためのインターフェースです。
別にこれなくても世代管理するクラスだけ作っちゃえばやりたいことは実現するのですが、
こういう汎用的な機能はインターフェース作ってimplementsして実装したほうが、拡張性が高かったりします。
※例えば全く異なる定義の状態を管理する必要がでてきたときに、このインターフェースを
 implementsして実装することで、利用者は統一した利用方法で実装できますね。

SimpleGenerationManageable.java
    /**
     * ステータスクラス.
     * <p>現在の状態と一つ前の状態を保持する。</p>
     */
    public static class Status implements SimpleGenerationManageable {
        /** 状態:未処理. */
        public static final int STATE_NONE = 0;
        /** 状態:待ち. */
        public static final int STATE_WAIT = 1;
        /** 状態:処理中. */
        public static final int STATE_PROCESSING = 2;

        /** 現在の状態. */
        private int mCurrent = STATE_NONE;
        /** ひとつ前の状態. */
        private int mBefore = STATE_NONE;

        /**
         * 状態をセットする.
         * @param state セットする状態.
         */
        void setStatus(int state) {
            mBefore = mCurrent;
            mCurrent = state;
        }

        @Override
        public int getCurrent() {
            return mCurrent;
        }

        @Override
        public int getBefore() {
            return mBefore;
        }

        @Override
        public boolean currentIs(int current) {
            return mCurrent == current;
        }

        @Override
        public boolean beforeIs(int before) {
            return mBefore == before;
        }
    }

状態を表すクラスの実装です。
今回の例では状態をセットするsetStatus(int state)の引数を状態値で受け取るようにしていますが、
SimpleGenerationManageableで定義したインターフェースを満たせば後は自由。
用途に合わせ状態を管理する処理を好きに作ることができます。
内部的にどんな実装にしていようが、利用者はSimpleGenerationManageableのインターフェースを通して
状態を調べるだけです。

終わりに

Androidのプログラミングで簡易的な世代管理はandroid.util.Pairを使って表現していたのですが、
なんだか読みにくいソースになってしまったので反省の意を込めての投稿でした。