Kotlin——進階篇(二): 簡單工廠模式詳解

繼上篇文章Kotlin——進階篇(一):設計模式概述發佈後相信你們對設計模式有了一個大概的瞭解,故而今天爲你們講解最簡單的一個設計模式:工廠模式java

工廠模式分爲工廠方法模式抽象工廠模式,其中,工廠方法模式有一個簡易的實現,被稱爲簡單工廠模式,而簡單工廠模式也可被稱爲靜態工廠方法模式git

限於篇幅緣由,我會分紅三篇文章來說解工廠模式,此篇文章主要講解簡單工廠模式,後續爲你們輸出工廠方法模式和抽象工廠模式的文章github

目錄

1、定義與做用

總的來講這不算23種設計模式中的一種,他實際上是工廠方法模式中的一個簡易版。在這裏單獨做爲一篇文章來寫,一是爲了篇幅考慮,二也是爲了能更好的理解及應用工廠方法模式,同時也爲下一篇文章作一個啓下的做用。設計模式

由於,此模式在新增新產品時會違背開-閉原則。故而這裏稱其爲簡單工廠模式,下面看它的定義與做用bash

1.一、定義與做用

  • 簡單工廠模式,又被稱爲靜態工廠方法模式
  • 是一種建立型的設計模式
  • 定義了一個具體的工廠類來負責建立其餘類的實例,被建立的實例一般都具備共同的父類。達到建立者和調用者的分離的目的

1.二、結構說明

簡單工廠模式由具體工廠(ConcreteFactory)、抽象產品(Product)、具體產品(ConcreteProduct)三部分構成app

  • 具體說明

  1. 具體工廠(ConcreteFactory):完成具體產品的建立。
  2. 抽象產品(Product):定義了產品的規範,描述了產品的主要特性和功能。
  3. 具體產品(ConcreteProduct):實現了抽象產品角色所定義的接口,由具體工廠來建立,它同具體工廠之間一一對應。
  • UML

2、分類與實例

簡單工廠模式分爲三類:ide

  1. 普通工廠模式
  2. 多個工廠方法模式
  3. 靜態工廠方法模式

下面,根據實例爲你們講解各類分類的具體實現及代碼:函數

: 此實例來至《Java與模式》書中,固然作了一部分修改post

現有三種水果(蘋果(Apple)、香蕉(Banana)、葡萄(Grape),它們都有着價格(price)屬性以及生長(grow)、收穫(harvest)方法。其中蘋果有一個顏色(color)屬性。葡萄有一個有籽或無籽屬性(seed)。現有一園丁,根據需求去採摘水果。測試

實現

步驟1:給三種水果定義一個抽象角色(IFruit),其中抽象角色能夠是接口或抽象類

interface IFruit{

   /**
    * 生長
    */
   fun grow()

   /**
    * 收穫
    */
   fun harvest()

   /**
    * 價格
    */
   var price : Double
   
}
複製代碼

步驟2:定義各個具體角色。

/ 定義蘋果類
class Apple(private val color : String, override var price: Double) : IFruit{

   override fun grow() {
       println("grow apple...")
   }

   override fun harvest() {
       println("harvest apple ...")
       println("I`m apple, color : $color \t price : $price")
   }
   
}

// 定義香蕉類
class Banana(override var price: Double) : IFruit{

   override fun grow() {
       println("grow banana...")
   }

   override fun harvest() {
       println("harvest banana ...")
       println("I`m banana, price : $price")
   }

}

// 定義葡萄類
class Grape(private val seed : Boolean, override var price: Double) : IFruit{

   override fun grow() {
       println("grow grape...")
   }

   override fun harvest() {
       println("harvest grape ...")
       println("I`m grape, seed : $seed \t price : $price")
   }
   
}
複製代碼

步驟3:實現工廠類,這裏根據上面的三種分類來定義,請繼續往下看,講述各個分類的特色以及上面實例的編寫

2.一、普通工廠模式

結合上面的代碼寫出普通工廠模式的工廠類代碼

class FirstFruitFactory{

    /**
     * 根據類型建立
     */
    fun createFactory(type : String) : IFruit?{
        return when(type){
            "apple" -> Apple("red", 12.8)
            "banana" -> Banana(8.8)
            "grape" -> Grape(false, 15.98)
            else -> null
        }
    }

}
複製代碼

測試類:

fun main(args : Array<String>){
    val firstFruit = FirstFruitFactory().createFactory("apple")
    firstFruit?.harvest()
}
複製代碼

輸出結果爲:

harvest apple ...
I`m apple, color : red 	 price : 12.8
複製代碼

分析

  • 當傳入的參數不知足建立具體產品類時,返回null對象或者可拋出異常。
  • 並且包含了稍顯複雜的if-else結構判斷.
  • 每次使用都需實例化工廠

爲了解決這些問題,引入多個工廠方法模式。優化一下代碼!

2.二、多個工廠方法模式

結合上面的代碼寫出多個工廠方法模式的工廠類代碼

class SecondFruitFactory{

    /**
     * 建立蘋果
     */
    fun createApple() : IFruit{
        return Apple("green", 8.8)
    }

    /**
     * 建立香蕉
     */
    fun createBanana() : IFruit{
        return Banana(5.5)
    }

    /**
     * 建立葡萄
     */
    fun createGrape() : IFruit{
        return Grape(true, 12.8)
    }

}
複製代碼

測試:

fun main(args : Array<String>){
    // 多個工廠方法測試
    val secondFruit = SecondFruitFactory().createBanana()
    secondFruit.harvest()
}
複製代碼

輸出結果爲:

harvest banana ...
I`m banana, price : 5.5
複製代碼

分析

從上面的代碼能夠看出,解決了一部分普通工廠模式的弊端。每次使用的時候仍是須要實例化工廠。故而要解決這個問題,引入下面的靜態工廠方法模式。這也是簡單工廠模式的最好實現,推薦此寫法

2.三、靜態工廠方法模式

結合上面的代碼寫出靜態工廠方法模式的工廠類代碼

class ThirdFruitFactory{

    companion object{
        /**
         * 建立蘋果
         */
        fun createApple() : IFruit{
            return Apple("green", 8.8)
        }

        /**
         * 建立香蕉
         */
        fun createBanana() : IFruit{
            return Banana(5.5)
        }

        /**
         * 建立葡萄
         */
        fun createGrape() : IFruit{
            return Grape(true, 12.8)
        }
    }
}
複製代碼

測試:

fun main(args : Array<String>){
    // 靜態工廠方法測試
    val thirdFruit = ThirdFruitFactory.createGrape()
    thirdFruit.harvest()
}
複製代碼

輸出結果爲:

harvest grape ...
I`m grape, seed : true 	 price : 12.8
複製代碼

3、合併

咱們知道一個簡單工廠模式,包含了一個工廠角色、一個抽象產品角色以及一個具體的角色。當出現下面三種狀況時,具體簡單工廠模式的寫法。

3.一、缺省抽象角色

當一個系統過於簡單,只有一個具體產品角色時,此時不須要抽象產品角色。咱們先看一個圖:

實現

步驟1:建立具體的產品角色

class ConcreteProduce{
    
    fun show(){
        println("show函數被調用")
    }
    
}
複製代碼

步驟2:建立工廠類

class ConcreteFactory{
    
    companion object{
        fun factory : ConcreteProduce{
            return ConcreteProduce()
        }
    }
    
}
複製代碼

測試:

fun main(args : Array<String>){
    val produce = ConcreteFactory.factory()
    produce.show()
}
複製代碼

3.二、抽象產品角色和工廠角色合併

在某些狀況下,工廠角色能夠由抽象產品角色扮演,即抽象產品角色同時是其子類的工廠,最具體的表現爲系統中的DateFormat類。看下面的圖:

這裏就不舉例說明了,有興趣的能夠去看看DateForamt類及其子類的實現。

3.三、三者皆合併

當抽象產品角色被省略時,工廠角色能夠和具體產品角色合併。換言之,就是一個產品類就是自身的工廠。看下面的圖:

具體的代碼爲:

class ConcreteProduce{

    companion object{
        fun createProduce() : ConcreteProduce{
            return ConcreteProduce()
        }
    }
    
    fun show(){
        println("show函數被調用了")
    }
}
複製代碼

測試:

fun main(){
    val produce = ConcreteProduce.createProduce()
    produce.show()
}
複製代碼

4、簡單工廠模式的優缺點

  • 優勢

    1. 該模式的核心在與工廠類,這個類能夠決定何時建立哪個具體產品的實例子。
    2. 客戶端能夠直接免除直接建立產品對象的責任,而只負責消費產品。簡單工廠模式經過這種方式實現了對責任的分離。
  • 缺點

    1. 因爲工廠類集中了全部產品建立邏輯,一旦不能正常工做,整個系統都要受到影響。
    2. 使用簡單工廠模式將會增長系統中類的個數,在必定程序上增長了系統的複雜度和理解難度。
    3. 系統擴展困難,一旦添加新產品就不得不修改工廠邏輯,一樣破壞了「開閉原則」;在產品類型較多時,有可能形成工廠邏輯過於複雜,不利於系統的擴展和維護。
    4. 簡單工廠模式因爲使用了靜態工廠方法,形成工廠角色沒法造成基於繼承的等級結構。
  • 適用場景

    工廠類負責建立的對象比較少:因爲建立的對象較少,不會形成工廠方法中的業務邏輯太過複雜。

總結

以上就是所有關於簡單工廠模式的知識點。請掌握它的結構組成以及優缺點,而且當結構組成部分可缺省或可合併時,也能判斷出該代碼是簡單工廠模式結構。

項目源代碼

若是各位大佬看了以後感受還闊以,就請各位大佬隨便star一下,您的關注是我最大的動力。
個人我的博客Jetictors
個人githubJetictors

歡迎各位大佬進羣共同研究、探索

QQ羣號:497071402

相關文章
相關標籤/搜索