この記事の一部は生成AIによって書かれています。
普段、実装していて「なんかNullチェックせずにいい感じにしたいなあ」と言う時ありませんか?
そんな時に覚えておくと役に立つかもしれないNull Object パターンをご紹介します。
Null Objectパターンとは?
Null Objectパターンは、nullの代わりに特定のインターフェースや抽象クラスを実装するオブジェクトを提供するデザインパターンです。このオブジェクトは「何もしない」か、もしくは安全なデフォルト動作を実装します。このパターンを使うことで、nullチェックの煩雑さを減らし、コードの可読性を向上させることができます。
実装例
実装例を示して説明していきます。(本筋じゃないところは説明省いてます )
Null Objectパターンを使用しない例
例として以下のような実装があったとします。
何かのイベント処理を実行するクラス
interface EventExecutor {
fun execute()
}
class SomethingExecutor: EventExecutor {
override fun execute() {
println("Execute something!")
}
}
Eventに対応するEventExecutorを返すクラス
Event定義など細かいところは割愛しています
class EventExecutorFactory {
companion object {
@JvmStatic
fun create(event: Event?): EventExecutor? {
return when(event) {
is Something -> SomethingExecutor()
else -> null
}
}
}
}
呼び出す
Kotlin
KotlinだとNull安全があるので、?.
でNullじゃない場合にexecute()
を呼び出します。
fun doSomething(event: Event?) {
EventExecutorFactory.create(event)?.execute()
}
Java
Kotlinだと簡素にかけますが、Javaとの相互運用が必要でJavaからこのコードを呼び出すとこんな風になります。
void doSomething(Event event) {
EventExecutor executor = EventExecutorFactory.create(event);
if(executor != null) {
executor.execute();
}
}
nullチェックを忘れるとぬるぽ(NullPointerException
)が発生する恐れがあります。(まあ、ただIDEが警告で教えてくれたりします。)
Null Objectパターンを使用する例
Null Objectを実装
NoopExecutor
という何もしないクラスを実装します。
class NoopExecutor: EventExecutor {
override fun execute() {
// noop
}
}
EventExecutorFactoryを修正
EventExecutorFactory.create
のnullを返していたところをNoopExecutorを返すように修正します。
class EventExecutorFactory {
companion object {
@JvmStatic
fun create(event: Event?): EventExecutor {
return when(event) {
is Something -> SomethingExecutor()
else -> NoopExecutor()
}
}
}
}
呼び出し側を修正
EventExecutorFactory.create
がnonNullになったのでNullチェックが不要になります。
Kotlin
fun doSomething(event: Event?) {
EventExecutorFactory.create(event).execute()
}
Java
void doSomething(Event event) {
EventExecutorFactory.create(event).execute();
}
Nullチェックが不要になりスッキリしました。
呼び出し元が複数ある場合には、複数箇所でNullチェックがあると辛いですが、Null Objectパターンを使うと呼び出し元がNullかどうか意識しなくて済みます。
まとめ
Null Object パターンのご紹介でした。
KotlinがNull安全かつ簡素にかけるのでそこまで利用シーンないかもしれませんが、Javaとの相互運用が必要だったり、Nullチェックしたくないなと言う時など、覚えておくと役に立つかもしれません。