模板方法模式
作用:在父类中编排主流程,将步骤实现延迟到子类去实现。
背景
Jack的水果店的售卖流程
![](https://img.haomeiwen.com/i20123021/4a74dd6b98211700.png)
通过观察我们可以知道大致流程基本相同,唯一不同点就是支付环节
实现设计
![](https://img.haomeiwen.com/i20123021/778bf110c677f75c.png)
1、先将主流程框架逻辑(清点商品、计算价格、结算、送货上门)设计完成。
2、再实现各模块小步骤。
3、不能确定的步骤,作为虚拟方法,甩锅给子类实现。
4、子类只需要聚焦自己的小步骤逻辑。
代码实例
package 设计模式9
/**
*@Description
*@Author PC
*@QQ 1578684787
*/
abstract class ShoppingCart(open var products:List<Fruit> = ArrayList()) {
//提交订单
fun submitOrder(){
//计算商品金额
val money = balance()
println("需要支付的总金额为${money}元")
//保存订单
pay(money)
//送货上门
sendHome()
}
//计算金额
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("三公里以内,免费送货上门")
}
//提交保存
abstract fun pay(money:Int)
}
class CashShopping(products:List<Fruit>):ShoppingCart(products) {
override fun pay(money: Int) {
println("现金结算")
}
}
class CartShopping(products: List<Fruit>) : ShoppingCart(products) {
override fun pay(money: Int) {
println("会员卡结算立减10元,金额:${money-10},增加积分:${money*10}")
}
}
class OnlineShopping(products:List<Fruit>):ShoppingCart(products) {
override fun pay(money: Int) {
println("微信支付宝支付立减5元,请支付:${money-5}元")
}
}
测试
fun main() {
val banana = Banana("香蕉",40)
val apple = Apple("苹果",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()
}
测试结果
![](https://img.haomeiwen.com/i20123021/c2438d1f2fdf6651.png)
应用场景
- 一次性实现程序的执行顺序和固定不变部分,课便比分则交由子类来实现。
- 多个子类中拥有相同的行为时,可以将其抽出来放在父类中,避免重复的代码。
- 使用钩子方法来让子类决定父类的某个步骤是否执行,实现子类对父类的反向控制。
- 控制子类扩展。模板方法只在特定点调用钩子方法,这样就只允许在这些点进行扩展
模板方法模式在Android中的应用:Android中的View的draw方法就是使用了模板方法模式。
优点
- 提高代码复用性,去除子类中的重复代码。
- 提高扩展性,不同实现细节放在不同子类中,易于增加新行为。
缺点
每一个不同的实现都需要定义一个类,这会导致类的个数的增加,设计更加抽象。
网友评论