【Kotlin/Android Studio】Factory Methodデザインパターンとは?
この記事からわかること
- Android Studio/Kotlinでみるデザインパターン:Factory Methodとは?
- 実装方法と役割
- Companion objectで実装する
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
参考文献:Wikipedia
参考文献:KotlinにおけるFactoryメソッドの実装パターン
環境
- Android Studio:Flamingo
- Kotlin:1.8.20
Factory Methodとは?
Factory Method(ファクトリーメソッド)とはオブジェクト指向ソフトウェアの設計に関する知見やノウハウに再利用性しやすいようにまとめたGoFのデザインパターンの1つです。その中でもFactory Methodはオブジェクトの生成(インスタンス化)処理を別クラスに委任することでインスタンス生成を抽象化する方法を提供します。
通常クラスをインスタンス化する際はコンストラクタ(イニシャライザ)などを使用してオブジェクトのインスタンスを取得するのが一般的です。
data class User(val name: String)
var user = User("ame")
一方Factory Methodではサブクラスの中にインスタンス化を行うためのメソッドを準備することでインスタンス化処理を切り出し、拡張性と再利用性を向上させることを目的としています。つまり先ほどのようなインスタンス化方法ではなく、メソッドを実行した返り値としてオブジェクトを取得します。そしてそのメソッドのことを「Factory Method」と呼ぶようです。
var user = ConcreteCreator().createProduct()
「Factory」は工場という意味なのでオブジェクトを生産するための工場クラスを別途用意するとイメージすると分かりやすいです。
メリット
コンストラクを使用せずにFactory Methodパターンで実装するメリットは以下の通りのようです。
- インスタンス化メソッドの名前が自由に変更できる
- サブクラスを返すこともできる
- シングルトンを返すことができる
- インスタンス化処理の中身を隠蔽できる
コンストラクタを使用するよりも柔軟性が大幅に向上し、また使用するクラスに不必要な情報を隠蔽することもできるようになります。
Factory Methodの登場人物
Factory Methodパターンには4つの登場人物が存在します。
- Creator:抽象クラス
- Product:抽象クラス
- ConcreteCreator:具象クラス
- ConcreteProduct:具象クラス
Creator:抽象クラス
インスタンスを生成するためのFactory Methodを定義する抽象的なクラス。抽象的な定義のみなので実際にの生成処理はサブクラスになるConcreteCreatorクラスへ委譲する
// Creator(製造者0クラスの抽象クラス
abstract class UserFactory {
abstract fun createUser(): User
fun displayUserType() {
val user = createUser()
user.displayName()
}
}
Product:抽象クラス
オブジェクト(製品)の共通のインターフェースを定義する抽象クラス。具体的な処理はConcreteProductクラスが持ち、このインターフェースをオーバーライドする
// Product(製品)クラスの抽象クラス
abstract class User {
abstract fun displayName()
}
ConcreteCreator:具象クラス
Creatorを継承し、具体的な製品を生成しするために抽象メソッドをオーバーライドする。実際のインスタンス生成処理とそれを返す役割がある
// ConcreteCreatorA (具体的な製造者A)クラス
class AdminUserFactory : UserFactory() {
override fun createUser(): User {
return AdminUser()
}
}
// ConcreteCreatorB (具体的な製造者B)クラス
class NormalUserFactory : UserFactory() {
override fun createUser(): User {
return NormalUser()
}
}
ConcreteProduct:具象クラス
Productを継承し、抽象メソッドを実装して具体的な製品の動作や振る舞いを提供する。
// ConcreteProductA (具体的な製品A)クラス
class AdminUser : User() {
override fun displayName() {
print("I am an admin user.")
}
}
// ConcreteProductB (具体的な製品B)クラス
class NormalUser : User() {
override fun displayName() {
print("I am a normal user.")
}
}
インスタンス化するときは以下のようになる。
val adminFactory = AdminUserFactory()
adminFactory.displayUserType() // 出力: "I am an admin user."
val normalFactory = NormalUserFactory()
normalFactory.displayUserType() // 出力: "I am a normal user."
Companion objectを使用する
companion object
を使用したFactory Methodパターンの実装方法もあるようです。
おすすめ記事:【Kotlin/Android Studio】Companion objectとは?staticなシングルトン
class User(val name: String) {
companion object {
fun from(name: String): User {
return User(name)
}
}
}
例えばRoomを使用する場合などに以下のように使用することがありました。
@Database(entities = [User::class], version = 1, exportSchema = false)
abstract class UserDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object {
@Volatile
private var INSTANCE: UserDatabase? = null
fun getDatabase(context: Context): UserDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
UserDatabase::class.java,
"user_database"
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
return instance
}
}
}
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。