【Kotlin/Android Studio】Factory Methodデザインパターンとは?

この記事からわかること

  • Android Studio/KotlinでみるデザインパターンFactory Methodとは?
  • 実装方法役割
  • Companion objectで実装する

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

参考文献:Wikipedia

参考文献:KotlinにおけるFactoryメソッドの実装パターン

環境

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つの登場人物が存在します。

  1. Creator:抽象クラス
  2. Product:抽象クラス
  3. ConcreteCreator:具象クラス
  4. 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
            }
        }
    }
}

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index