21种设计模式
这个设计模式系列的文章
对象创建模式
设计模式是为了解决一类问题而出现的,要深刻理解某个模式的应用场景,优点,缺点。千万不要为了使用而实用,那样很可能写出不伦不类的东西。
何为原型?
原型可以理解为模版,在创建新的对象的时候,按照模板的方式来复制。这样避免了重新创造轮子。
简单理解就是:创建第一个模板对象,然后通过复制模板来创建新的对象,还记得UITableviewCell的Deque方法吗?这其实就是一个“原型”,
解决什么问题?
- 解决了每次创建新的对象,都需要alloc init,这样就造成了代码要直接访问具体的类,也就增加了代码的耦合度。
- 避免创建工厂类的子类(例如抽象工厂模式)
- 通过copy能够保存对象当时的状态
什么时候使用原型模式?
- 需要创建的对象不依赖于具体的类型以及创建方式
- 具体实例化的对象类型是在运行期决定的
- 不同类型之间的差异紧紧是状态的组合
- 类型创建不容易,例如类型有复杂的嵌套
原型模式的UML图
实现原理
- Swift/Objective C并不支持抽象基或者抽象方法。但是可以使用协议类似定义一个抽象的“基类”,定义通用的属性,方法,以及复制方法。
- 具体的类负责实现复制方法,以及公用的方法。
- 通过抽象基类的接口创建对象
Swift 2.1例子
例子是要存储复杂的嵌套数据结构
假设我有一个绘图类LeoDrawer,那么这个Drawer必然要保存每一步后操作的结果,这样我能够进行redo和undo(可以用NSUndoManager,这里只是举例)。类似这种快照就是原型模式的典型场景
定义原型
protocol Shape{
var location:CGPoint{get set}
func draw()
func clone()->Shape
}
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
具体的类
class RoundShape: Shape {
var location:CGPoint
init(location:CGPoint){
self.location = location
}
func draw() {
}
func clone() -> Shape {
let shape = RoundShape(location: self.location)
return shape
}
}
class RectShape:Shape {
var location:CGPoint
init(location:CGPoint){
self.location = location
}
func draw() {
}
func clone() -> Shape {
let shape = RectShape(location: self.location)
return shape
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
客户端
class LeoDrawer{
var shapes:[Shape]?
}
let drawer = LeoDrawer()
drawer.shapes = [RoundShape(location: CGPointMake(1, 1)),RectShape(location: CGPointMake(10, 10))]
let shapesSnapshot = drawer.shapes?.map({ (shape) -> Shape in
return shape.clone()
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
优点
在扩展的时候,子类遵循原型的协议,很容易的扩展。并且,客户端代码不需要任何修改
提高技能如同提升自信心。