回答編集履歴
1
enumについてちょっと説明追加
test
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
1. **余分なインスタンスは作成されません。**
|
2
2
|
|
3
|
-
列挙型enumと言うのは静的不変インスタンスの集合で
|
3
|
+
列挙型`enum`と言うのは静的不変インスタンスの集合です。列挙された要素は`static final`なインスタンスのような特徴を持ち、`enum`のクラスがロードされた段階で列挙された要素(この場合`LOGGING`,`STOPPED`)のインスタンスが作成されて変数として保持されます。`setState`で渡しているインスタンスはこの`State`クラスですでに作成されているインスタンスへの参照を代入していることにほかなりません。`setState`の段階でインスタンスを作成しているわけではありません。
|
4
4
|
|
5
|
-
それよりもこのリファクタリングで目的としていることは、**想定外の状態を代入しないこと**です。元のコードでは、状態としてintの値を利用しています。しかし、状態を表すのは0と1のみで、他は「異常な状態」です。しかし、int値としては当然それ以外の値も入り得るため、安全性に欠けます。そこで状態に列挙型を利用すると、列挙型で挙げられたインスタンス以外を指定することが不可能になるため(指定するとコンパイルエラーになる)、安全性が高まります。
|
5
|
+
それよりもこのリファクタリングで目的としていることは、**想定外の状態を代入しないこと**です。元のコードでは、状態として`int`の値を利用しています。しかし、状態を表すのは0と1のみで、他は「異常な状態」です。しかし、`int`値としては当然それ以外の値も入り得るため、安全性に欠けます。そこで状態に列挙型を利用すると、列挙型で挙げられたインスタンス以外を指定することが不可能になるため(指定するとコンパイルエラーになる)、安全性が高まります。
|
6
6
|
|
7
7
|
|
8
8
|
|
9
|
-
2. StateLogging,StateStopped以外のStateを作成され、想定外の動きをさせられる恐れがあります。
|
9
|
+
2. `StateLogging`,`StateStopped`以外のStateを作成され、想定外の動きをさせられる恐れがあります。
|
10
10
|
|
11
|
-
前述のとおりenumを使った場合新たなインスタンスを生成しないのに対し、こちらは新たなインスタンスをメソッドの起動のたびに生成するというデメリットが有ります。仮にこの2つのクラスのインスタンスを1つ生成し、どこかのクラスのstatic finalフィールドにおいておき、それを使えばそのような問題はなくなります。
|
11
|
+
前述のとおり`enum`を使った場合新たなインスタンスを生成しないのに対し、こちらは新たなインスタンスをメソッドの起動のたびに生成するというデメリットが有ります。仮にこの2つのクラスのインスタンスを1つ生成し、どこかのクラスの`static final`フィールドにおいておき、それを使えばそのような問題はなくなります。
|
12
12
|
|
13
|
-
しかし一方で、引数として受け取っているのが抽象クラスStateであることから、**ユーザーが自身でこれを継承し、独自の実装をしてこのメソッドに渡すことが可能になってしまいます。**セキュリティの観念からこれは望ましくないことは明白です。Stateクラスをパッケージプライベートにして、2つの状態クラスをfinalに指定するという方法が考えられますが、それらをすべて実現できるenumの利便性には劣ります。
|
13
|
+
しかし一方で、引数として受け取っているのが抽象クラス`State`であることから、**ユーザーが自身でこれを継承し、独自の実装をしてこのメソッドに渡すことが可能になってしまいます。**セキュリティの観念からこれは望ましくないことは明白です。`State`クラスをパッケージプライベートにして、2つの状態クラスを`final`に指定するという方法が考えられますが、それらをすべて実現できる`enum`の利便性には劣ります。
|