SingletonパターンとBuilderパターンを使って、Firebase Analyticsをシンプルに使いやすくする

# 背景と概要
Firebase Analyticsをリファレンスを元にシンプルに設定すると以下のコードのようになる。
[quickstart-android](https://github.com/hinom77/quickstart-android/blob/master/analytics/app/src/main/java/com/google/firebase/quickstart/analytics/MainActivity.java)

```java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    // ① FirebaseAnalyticsインスタンスをクラス内全体で利用出来るようフィールドに定義
    private FirebaseAnalytics mFirebaseAnalytics;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // ② onCreateのタイミングでFirebaseAnalyticsインスタンスをセット
        mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);

        TextView helloWorld = (TextView) findViewById(R.id.hello_world);
        helloWorld.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.hello_world) {
            // ③ 「Hello World!」のテキストがクリックされるとイベントログを発火
            Bundle params = new Bundle();
            params.putString("param1", "test");
            params.putInt("param2", 100);
            params.putDouble("param3", 3.14);
            mFirebaseAnalytics.logEvent("event1", params);
        }
    }
}
```

リファレンス通りにコードを書くと上記のように、**FirebaseAnalyticsのインスタンスの定義箇所**、**そのインスタンスの設定箇所**、**そのインスタンスを用いたイベントログ発火箇所**がバラバラである。
これでは各クラス内でのFirebaseAnalyticsのインスタンスの管理もしづらく、FirebaseAnalyticsを使いにくい。
*そのため、今回デザインパターンのSingletonパターンを用いて、クラス内でのFirebaseAnalyticsのインスタンスの管理を簡単に出来るようにすることを考える。*

また、上記とは別にイベントログに付加するパラメータの設定部分も**パラメータが多くなるほど冗長に**なり、出来ればこの部分もよりシンプルに（例えばチェーンメソッドを用いるなど）パラメータを設定できるようにしたい。
*こちらの課題も、デザインパターンのBuilderパターンを使って、イベントログに付加するパラメータの設定部分をよりシンプルにすることを考える。*

# 1. Singletonパターンを用いて、インスタンスの定義からイベントログ発火までをよりシンプルに
Singletonパターンを用いて、以下のようにFirebaseAnalyticsHelperクラスを実装する。
なお、Singletonパターンについては、[Wikipediaに掲載のもの](https://ja.wikipedia.org/wiki/Singleton_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)を参考にした。

```java
public class FirebaseAnalyticsHelper {

    // ① FirebaseAnalyticsインスタンスをフィールドに定義
    private FirebaseAnalytics mFirebaseAnalytics;

    // ②　『Singletonパターン』でFirebase Analyticsインスタンスを設定
    private static FirebaseAnalyticsHelper sInstance;
    private FirebaseAnalyticsHelper(Context context){
        mFirebaseAnalytics = FirebaseAnalytics.getInstance(context.getApplicationContext());
    }
    public static synchronized FirebaseAnalyticsHelper getInstance(Context context){
        if(sInstance == null){
            sInstance = new FirebaseAnalyticsHelper(context);
        }
        return sInstance;
    }

    // ③ イベントログを発火するメソッドを作成
    public void logEvent(@NonNull final String name, Bundle params) {
        mFirebaseAnalytics.logEvent(name, params);
    }
    public void logEvent(@NonNull final String name) {
        mFirebaseAnalytics.logEvent(name, null);
    }
}
```

このFirebaseAnalyticsHelperクラスを用いて前述のMainActivityに適用すると、以下のように**FirebaseAnalyticsに関してのコードを記載するのが、イベントログを発火する部分のみで良くなる。**

```java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView helloWorld = (TextView) findViewById(R.id.hello_world);
        helloWorld.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.hello_world) {
            //「Hello World!」のテキストがクリックされるとイベントログを発火
            Bundle params = new Bundle();
            params.putString("param1", "test");
            params.putInt("param2", 100);
            params.putDouble("param3", 3.14);
            FirebaseAnalyticsHelper.getInstance(this).logEvent("event1", params);
        }
    }
}
```

以下にサンプルのコードを置いている。
[hinom77/SimpleFirebaseAnalytics ~ Branch: feature_singleton](https://github.com/hinom77/SimpleFirebaseAnalytics/tree/feature_singleton/app/src/main/java/com/example/hinom77/firebaseanalyticssample)


# 2. Builderパターンを用いて、パラメータの管理をよりシンプルに
Builderパターンを用いて、以下のようにFirebaseAnalyticsParamsクラスを実装する。
なお、Builderパターンについては、[Javaで書くBuilderパターンのパターン](http://qiita.com/disc99/items/840cf9936687f97a482b)の記事のように様々なパターンがあるが、ここでは**Effective Java Builder**を用いている。

```java
public class FirebaseAnalyticsParams {

    // ① 『Builderパターン』でパラメータ設定を定義
    private Bundle mParams;
    private FirebaseAnalyticsParams(Builder builder) {
        mParams = builder.params;
    }
    public static class Builder {
        private Bundle params = new Bundle();

        public Builder param1(String param1) {
            params.putString("param1", param1);
            return this;
        }

        public Builder param2(Integer param2) {
            params.putInt("param2", param2);
            return this;
        }

        public Builder param3(Double param3) {
            params.putDouble("param3", param3);
            return this;
        }

        public FirebaseAnalyticsParams build() {
            return new FirebaseAnalyticsParams(this);
        }
    }

    // ② Paramsの値をBundle型で返す
    public Bundle getBundleParams() {
        return mParams;
    }
}
```

このFirebaseAnalyticsParamsクラスを用いて前述のMainActivityに適用すると、以下のように**パラメータ設定部分のコードが変数がいくつあっても１行で済み**、非常にシンプルになる。

```java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView helloWorld = (TextView) findViewById(R.id.hello_world);
        helloWorld.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.hello_world) {
            //「Hello World!」のテキストがクリックされるとイベントログを発火
            FirebaseAnalyticsParams params = new FirebaseAnalyticsParams
                    .Builder().param1("test").param2(100).param3(3.14).build();
            FirebaseAnalyticsHelper.getInstance(this).logEvent("event1", params);
        }
    }
}
```

なお、FirebaseAnalyticsHelperクラスも、上記に対応させて一部書き換える必要があるので注意が必要である。

以下にサンプルのコードを置いている。
[hinom77/SimpleFirebaseAnalytics ~ Branch: feature_builder](https://github.com/hinom77/SimpleFirebaseAnalytics/tree/feature_builder/app/src/main/java/com/example/hinom77/firebaseanalyticssample)