iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 20
0

簡介

工廠模式是一種設計模式。工廠顧名思義就是生產產品的地方,我們會宣告一個工廠類別,當我們需要產品的時候,就呼叫工廠類別,工廠就會回傳一個實例化的物件給我們。工廠模式又分成簡單工廠模式、工廠模式及抽象工廠模式。
以下用Kotlin來講解

簡單工廠模式

宣告一個類別,藉由傳入不同參數取得不同的類別。

簡單工廠模式是管理物件創建的地方,傳入不同的參數,會回傳不同的物件。使用者只要傳入正確參數,不需要理解這個物件是如何創建的。

舉個例子,現在我們要設計一個培訓冒險者的訓練營,裡面可以訓練兩種職業,弓箭手與鬥士。套到工廠模式中,我們會需要宣告一個冒險者類別(父類別)(介面),一個繼承並實作它的弓箭手類別及一個鬥士類別,以及一個訓練營類別,也就是簡單工廠類別。

  • 冒險者介面
// 冒險者
interface Adventurer {
    val type: String?
}

// 弓箭手
class Archer : Adventurer {
    override val type = "我是弓箭手"
}

// 鬥士
class Warrior : Adventurer {
    override val type = "我是鬥士"

}
  • 訓練營。也就是一個簡單工廠。我們只需要一個工廠實例,所以我們利用單例模式,也就是使用object來宣告它。
object TrainingCamp {
    fun trainAdventurer(type: String?): Adventurer? {
        return when (type) {
            "archer" -> {
                println("訓練一個弓箭手")
                Archer()
            }
            "warrior" -> {
                println("訓練一個鬥士")
                Warrior()
            }
            else -> null
        }
    }
}
  • 執行層
fun main(args: Array<String>) {

        val memberA = TrainingCamp.trainAdventurer("archer")
        val memberB = TrainingCamp.trainAdventurer("warrior")

        println(memberA?.type)
        println(memberB?.type)
}
執行結果:
訓練一個弓箭手
訓練一個鬥士
我是弓箭手
我是鬥士
  • 小結
    1.假如我們需要加入一種新的職業,我們就要在trainAdventurer方法內的when判斷式新增一個選項。這樣直接修改工廠類別的行為,違反了開放/封閉原則,因此簡單工廠模式不算是一個健全的設計模式。但簡單工廠模式在小型軟體架構中其實是很好用的。
    2.工廠類包含了所有例項(產品)的建立邏輯,若工廠類出錯,則會造成整個系統都會會受到影響。

工廠模式

將工廠提升到抽象介面,各個子類別工廠依其需求各自實作。

簡單工廠模式因為只有一個工廠,新增產品類別時會需要直接修改工廠內部的程式碼,破壞了開放/封閉原則。在這裡我們將工廠提升為抽象介面,這個工廠介面只會規範其子類別應該回傳哪種產品,實際上要如何製作產品則交給子類別各自實作。

現在工廠已被提升為一種概念,每種冒險者的訓練過程應該是不同的,例如訓練後勤掩護的弓箭手與訓練進戰的鬥士應該是不同的培訓過程,不能像以前一樣一個訓練營訓練出所有種類的冒險者。

  • 冒險者介面。
  • 子類別:
    1.鬥士
    2.弓箭手
    --------------------這裡跟前面一樣。
interface Adventurer {
    val type: String?
}

// 弓箭手
class Archer : Adventurer {
    override val type = "我是弓箭手"
}

// 鬥士
class Warrior : Adventurer {
    override val type = "我是鬥士"

}
  • 訓練營介面。
  • 子類別:
    1.培訓鬥士的訓練營
    2.培訓弓箭手的訓練營
interface TrainingCamp{
    fun trainAdventurer():Adventurer
}

object ArcherTrainingCamp:TrainingCamp {
    override fun trainAdventurer(): Adventurer {

        println("訓練一個弓箭手")
        return Archer()

    }
}

object WarriorTrainingCamp:TrainingCamp {
    override fun trainAdventurer(): Adventurer{

        println("訓練一個鬥士")
        return Warrior()
    }
}
  • 執行層
fun main(args: Array<String>) {
    val memberA = ArcherTrainingCamp.trainAdventurer()
    val memberB = WarriorTrainingCamp.trainAdventurer()

    println(memberA?.type)
    println(memberB?.type)
}
執行結果:
訓練一個弓箭手
訓練一個鬥士
我是弓箭手
我是鬥士

新手村現在建立了兩座訓練營,弓箭手訓練營、鬥士訓練營。如此一來,若想修改弓箭手的訓練流程,就修改弓箭手訓練營裡的程式碼即可,不用擔心會影響鬥士訓練營的運作,而且如要增加冒險者的類別,例如劍士,只要新增一座劍士訓練營,完全不會改動到抽象訓練營與本來的實體訓練營。

累惹,今天先到這,明天再來講抽象工廠。


上一篇
Android : 淺淺淺談記憶體洩漏Memory leak
下一篇
Android x Kotlin : 工廠模式淺解[下]
系列文
Android Kotlin開發 -小嫩雞的30篇精選筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言