模板方法模式
作用:在父類中編排主流程,將步驟實(shí)現(xiàn)延遲到子類去實(shí)現(xiàn)。
背景
Jack的水果店的售賣流程

image.png
通過(guò)觀察我們可以知道大致流程基本相同,唯一不同點(diǎn)就是支付環(huán)節(jié)
實(shí)現(xiàn)設(shè)計(jì)

image.png
1、先將主流程框架邏輯(清點(diǎn)商品、計(jì)算價(jià)格、結(jié)算、送貨上門)設(shè)計(jì)完成。
2、再實(shí)現(xiàn)各模塊小步驟。
3、不能確定的步驟,作為虛擬方法,甩鍋給子類實(shí)現(xiàn)。
4、子類只需要聚焦自己的小步驟邏輯。
代碼實(shí)例
package 設(shè)計(jì)模式9
/**
*@Description
*@Author PC
*@QQ 1578684787
*/
abstract class ShoppingCart(open var products:List<Fruit> = ArrayList()) {
//提交訂單
fun submitOrder(){
//計(jì)算商品金額
val money = balance()
println("需要支付的總金額為${money}元")
//保存訂單
pay(money)
//送貨上門
sendHome()
}
//計(jì)算金額
private fun balance():Int{
var money:Int = 0
println("商品清單:")
for (fruit in products){
Factory.pack(fruit,fruit.price)
println("${fruit.name},${fruit.price}")
money+=fruit.price
}
return money
}
private fun sendHome(){
println("三公里以內(nèi),免費(fèi)送貨上門")
}
//提交保存
abstract fun pay(money:Int)
}
class CashShopping(products:List<Fruit>):ShoppingCart(products) {
override fun pay(money: Int) {
println("現(xiàn)金結(jié)算")
}
}
class CartShopping(products: List<Fruit>) : ShoppingCart(products) {
override fun pay(money: Int) {
println("會(huì)員卡結(jié)算立減10元,金額:${money-10},增加積分:${money*10}")
}
}
class OnlineShopping(products:List<Fruit>):ShoppingCart(products) {
override fun pay(money: Int) {
println("微信支付寶支付立減5元,請(qǐng)支付:${money-5}元")
}
}
測(cè)試
fun main() {
val banana = Banana("香蕉",40)
val apple = Apple("蘋(píng)果",50)
val shopping = OnlineShopping(listOf(banana,apple))
shopping.submitOrder()
val shopping2 = CashShopping(listOf(banana,apple))
shopping2.submitOrder()
val shopping3 = CartShopping(listOf(banana,apple))
shopping3.submitOrder()
}
測(cè)試結(jié)果

測(cè)試結(jié)果
應(yīng)用場(chǎng)景
- 一次性實(shí)現(xiàn)程序的執(zhí)行順序和固定不變部分,課便比分則交由子類來(lái)實(shí)現(xiàn)。
- 多個(gè)子類中擁有相同的行為時(shí),可以將其抽出來(lái)放在父類中,避免重復(fù)的代碼。
- 使用鉤子方法來(lái)讓子類決定父類的某個(gè)步驟是否執(zhí)行,實(shí)現(xiàn)子類對(duì)父類的反向控制。
- 控制子類擴(kuò)展。模板方法只在特定點(diǎn)調(diào)用鉤子方法,這樣就只允許在這些點(diǎn)進(jìn)行擴(kuò)展
模板方法模式在Android中的應(yīng)用:Android中的View的draw方法就是使用了模板方法模式。
優(yōu)點(diǎn)
- 提高代碼復(fù)用性,去除子類中的重復(fù)代碼。
- 提高擴(kuò)展性,不同實(shí)現(xiàn)細(xì)節(jié)放在不同子類中,易于增加新行為。
缺點(diǎn)
每一個(gè)不同的實(shí)現(xiàn)都需要定義一個(gè)類,這會(huì)導(dǎo)致類的個(gè)數(shù)的增加,設(shè)計(jì)更加抽象。