介绍
- 1.定义了一个模板结构,将具体的内容延迟到子类中去执行
- 2.子类可以不改变算法结构,可以重新定义算法的某些特定步骤
主要作用
在不改变模板结构的前提下再子类中重新定义模板中的内容
模板方法模式是基于“继承”的
解决问题
- 提高代码的复用性
- 将相同部分代码放在抽象的父类中,而将不同的代码放入不同的子类中
- 实现了反向控制
- 通过一个父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制&复合“开闭原则”
模板方法模式->案例
实现一个播放器:
- 角色一:模板类->TemplateAVPlayer
- 角色二:实现类->DefaultAVPlayer
首先要确定TemplateAVPlayer模板方法,根据播放流程创建模板方法:
- 1.创建播放器
- 2.准备播放器(设置基本参数)
- 3.添加监听器
- 4.开始播放
抽象模板方法类TemplateAVPlayer
class TemplateAVPlayer: NSObject {
public var delegate:AVPlayerDelegate?
//定义模版方法->提供给外部
final func play(controller:UIViewController, frame:CGRect, url:String){
self.create(url: url)
self.prepare(controller: controller, frame: frame)
self.observer()
self.paly()
}
//模版方法
func create(url:String) {
}
//模版方法
func prepare(controller:UIViewController, frame:CGRect) {
}
//模版方法
func observer() {
}
//模版方法
func paly() {
}
func pause() {
}
func stop() {
}
}
具体的模板方法类->DefaultAVPlayer
class DefaultAVPlayer: TemplateAVPlayer {
private var player:AVPlayer?
private var playerItem:AVPlayerItem?
override func create(url: String) {
//1、创建播放器
self.playerItem = AVPlayerItem(url: URL(fileURLWithPath: url))
self.player = AVPlayer(playerItem: self.playerItem)
}
override func prepare(controller: UIViewController, frame: CGRect) {
//2.1 创建图层
let playerLayer = AVPlayerLayer(player: self.player)
playerLayer.frame = frame
controller.view.layer.addSublayer(playerLayer)
}
override func observer() {
//2.2 设置监听
NotificationCenter.default.addObserver(self, selector: #selector(stop), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
//2.3 添加监听
self.playerItem?.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.new, context: nil)
}
override func paly() {
self.player?.play()
}
//语法
@objc override func stop() {
}
//播放器状态改变
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("回调了...")
if keyPath == "status" {
//设置监听->外部处理
self.delegate?.playerCall(status: self.playerItem?.status)
if self.playerItem?.status == AVPlayerItemStatus.failed {
print("加载错误")
} else if self.playerItem?.status == AVPlayerItemStatus.unknown {
print("未知错误")
} else {
print("播放正常...")
}
}
}
//析构函数
deinit {
//释放资源
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
self.playerItem?.removeObserver(self, forKeyPath: "status")
}
}
客户端调用:
let path = Bundle.main.path(forResource: "Test", ofType: ".mov")
let player = DefaultAVPlayer()
player.delegate = self
player.play(controller: self, frame: self.view.frame, url: path!)
这样使用模板方法模式处理,优化了代码的结构,这样的扩展性更强,只需要继承DefaultAVPlayer,实现模板方法,就可以实现具体的扩展
其实模板方法模式在iOS中也有很多的应用例如UIViewController其实就是模板方法模式->生命周期固定、第三方的下拉刷新组件(详情请看下一篇MJRefresh的解析)