繼上篇文章Kotlin——進階篇(一):設計模式概述發佈後相信你們對設計模式有了一個大概的瞭解,故而今天爲你們講解最簡單的一個設計模式:工廠模式。java
工廠模式分爲工廠方法模式和抽象工廠模式,其中,工廠方法模式有一個簡易的實現,被稱爲簡單工廠模式,而簡單工廠模式也可被稱爲靜態工廠方法模式git
限於篇幅緣由,我會分紅三篇文章來說解工廠模式,此篇文章主要講解簡單工廠模式,後續爲你們輸出工廠方法模式和抽象工廠模式的文章github
總的來講這不算23
種設計模式中的一種,他實際上是工廠方法模式中的一個簡易版。在這裏單獨做爲一篇文章來寫,一是爲了篇幅考慮,二也是爲了能更好的理解及應用工廠方法模式,同時也爲下一篇文章作一個啓下的做用。設計模式
由於,此模式在新增新產品時會違背開-閉原則。故而這裏稱其爲簡單工廠模式,下面看它的定義與做用bash
- 簡單工廠模式,又被稱爲靜態工廠方法模式
- 是一種建立型的設計模式
- 定義了一個具體的工廠類來負責建立其餘類的實例,被建立的實例一般都具備共同的父類。達到建立者和調用者的分離的目的
簡單工廠模式由具體工廠(ConcreteFactory
)、抽象產品(Product
)、具體產品(ConcreteProduct
)三部分構成app
- 具體工廠(
ConcreteFactory
):完成具體產品的建立。- 抽象產品(
Product
):定義了產品的規範,描述了產品的主要特性和功能。- 具體產品(
ConcreteProduct
):實現了抽象產品角色所定義的接口,由具體工廠來建立,它同具體工廠之間一一對應。
UML
圖簡單工廠模式分爲三類:ide
- 普通工廠模式
- 多個工廠方法模式
- 靜態工廠方法模式
下面,根據實例爲你們講解各類分類的具體實現及代碼:函數
例: 此實例來至《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:實現工廠類,這裏根據上面的三種分類來定義,請繼續往下看,講述各個分類的特色以及上面實例的編寫
結合上面的代碼寫出普通工廠模式的工廠類代碼
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
結構判斷.爲了解決這些問題,引入多個工廠方法模式。優化一下代碼!
結合上面的代碼寫出多個工廠方法模式的工廠類代碼
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
複製代碼
分析
從上面的代碼能夠看出,解決了一部分普通工廠模式的弊端。每次使用的時候仍是須要實例化工廠。故而要解決這個問題,引入下面的靜態工廠方法模式。這也是簡單工廠模式的最好實現,推薦此寫法
結合上面的代碼寫出靜態工廠方法模式的工廠類代碼
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
複製代碼
咱們知道一個簡單工廠模式,包含了一個工廠角色、一個抽象產品角色以及一個具體的角色。當出現下面三種狀況時,具體簡單工廠模式的寫法。
當一個系統過於簡單,只有一個具體產品角色時,此時不須要抽象產品角色。咱們先看一個圖:
實現
步驟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()
}
複製代碼
在某些狀況下,工廠角色能夠由抽象產品角色扮演,即抽象產品角色同時是其子類的工廠,最具體的表現爲系統中的DateFormat
類。看下面的圖:
這裏就不舉例說明了,有興趣的能夠去看看DateForamt
類及其子類的實現。
當抽象產品角色被省略時,工廠角色能夠和具體產品角色合併。換言之,就是一個產品類就是自身的工廠。看下面的圖:
具體的代碼爲:
class ConcreteProduce{
companion object{
fun createProduce() : ConcreteProduce{
return ConcreteProduce()
}
}
fun show(){
println("show函數被調用了")
}
}
複製代碼
測試:
fun main(){
val produce = ConcreteProduce.createProduce()
produce.show()
}
複製代碼
優勢
- 該模式的核心在與工廠類,這個類能夠決定何時建立哪個具體產品的實例子。
- 客戶端能夠直接免除直接建立產品對象的責任,而只負責消費產品。簡單工廠模式經過這種方式實現了對責任的分離。
缺點
- 因爲工廠類集中了全部產品建立邏輯,一旦不能正常工做,整個系統都要受到影響。
- 使用簡單工廠模式將會增長系統中類的個數,在必定程序上增長了系統的複雜度和理解難度。
- 系統擴展困難,一旦添加新產品就不得不修改工廠邏輯,一樣破壞了「開閉原則」;在產品類型較多時,有可能形成工廠邏輯過於複雜,不利於系統的擴展和維護。
- 簡單工廠模式因爲使用了靜態工廠方法,形成工廠角色沒法造成基於繼承的等級結構。
適用場景
工廠類負責建立的對象比較少:因爲建立的對象較少,不會形成工廠方法中的業務邏輯太過複雜。
以上就是所有關於簡單工廠模式的知識點。請掌握它的結構組成以及優缺點,而且當結構組成部分可缺省或可合併時,也能判斷出該代碼是簡單工廠模式結構。
若是各位大佬看了以後感受還闊以,就請各位大佬隨便star
一下,您的關注是我最大的動力。
個人我的博客:Jetictors
個人github:Jetictors