iOS - 模版方法模式

定义

模版方法模式:定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。(Template Method Pattern: Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

简单来说:定义一个父类,由父类定义接口规范,然后不同的行为在子类中实现。

通用类图

download.png

可以看到模版方法模式非常简单,抽象类方法分为两类:

基本方法:基本方法也叫基本操作,是由子类实现的方法,并且在模版方法中被调用

模版方法:可以有一个或几个,一般是一个具体方法,也就是一个模版,实现具体的调用逻辑

类图实现

使用父类实现模版方法

public class AbstractClass {
    func doSomething() {}
    func doAnything() {}
    
    func hook() -> Bool  { // 钩子方法
        return true
    }

    func templateMethod() {
        if hook() { doSomething() }
        doAnything()
    }
}

class ConcreteClass1: AbstractClass {
    // 实现基本方法
    override func doSomething() {
        //业务逻辑处理
        print("ConcreteClass1 doSomething")
    }

    override func doAnything() {
        //业务逻辑处理
        print("ConcreteClass1 doAnything")
    }

    override func hook() -> Bool {
        return false
    }
}

class ConcerteClass2: AbstractClass {
    // 实现基本方法
    override func doSomething() {
        //业务逻辑处理
        print("ConcreteClass2 doSomething")
    }

    override func doAnything() {
        //业务逻辑处理
        print("ConcreteClass2 doAnything")
    }
}

使用协议实现模版方法

protocol AbstractProtocol {
    func doSomething()
    func doAnything()
    func hook() -> Bool
    func templateMethod()
}

extension AbstractProtocol {
    func hook() -> Bool { // 钩子方法
        return true
    }
    func templateMethod() {
        if hook() { doSomething() }
        doAnything()
    }
}

class ConcreteClass1: AbstractProtocol {
    // 实现基本方法
    func doSomething() {
        //业务逻辑处理
        print("ConcreteClass1 doSomething")
    }

    func doAnything() {
        //业务逻辑处理
        print("ConcreteClass1 doAnything")
    }

    func hook() -> Bool {
        return false
    }
}

class ConcerteClass2: AbstractProtocol {
    // 实现基本方法
    func doSomething() {
        //业务逻辑处理
        print("ConcreteClass2 doSomething")
    }

    func doAnything() {
        //业务逻辑处理
        print("ConcreteClass2 doAnything")
    }
}

简单使用

let class1 = ConcreteClass1()
let class2 = ConcerteClass2()

class1.templateMethod()
class2.templateMethod()

//ConcreteClass1 doAnything
//ConcreteClass2 doSomething
//ConcreteClass2 doAnything

模版方法模式的优点

  • 封装不变部分,扩展可变部分。即把认为不变部分的算法封装到父类实现,而可变部分的则可以通过继承来继续扩展

  • 提取公共部分代码,便于维护

  • 行为由父类控制,子类实现

模版方法模式的缺点

  • 按照平时的设计习惯,抽象类负责最抽象、最一般的事物属性和方法,实现类完成具体的事物属性和方法,但是模版方法模式却颠倒了,抽象类定义了部分抽象方法,由子类实现,子类执行的结果影响了父类的结果,也就是子类对父类产生了影响,这在复杂的项目中,会带来代码阅读的难度

  • 每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。

模版方法模式的使用场景

  • 多个子类有公有的方法,并且基本逻辑相同

  • 重要 、复杂的算法,可以把核心算法设计为模版方法,相关的细节功能则由各个子类实现

  • 重构时,模版方法模式就是经常使用的模式,把相同的代码抽取到父类中,然后通过钩子方法(即抽象类中添加的新方法,该方法用于在模版方法中规避某些操作)约束其行为

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 设计模式概述 在学习面向对象七大设计原则时需要注意以下几点:a) 高内聚、低耦合和单一职能的“冲突”实际上,这两者...
    彦帧阅读 9,159评论 0 14
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明AI阅读 16,041评论 3 119
  • 说的很对,钱也许买不来快乐,但是钱却可以解决掉95%让我们不快乐的事情。
    发发爱学习阅读 1,196评论 0 0
  • 亲爱的,你是不是有过想要一夜暴富的美梦?想买到一张彩票中了头奖,然后计划着这巨额款该如何支配;或者是想自己的努力突...
    桐生影阅读 2,615评论 0 0
  • 在这个春日明媚的四月,不论是女明星还是美妆达人,纷纷抛弃冬季厚重的妆容,开始以✨清新无暇的美肌亮相! 活动亮点: ...
    Amylee2018阅读 1,449评论 0 0