原型模式

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。GoF提出了23种设计模式,本系列将使用Swift语言来实现这些设计模式

概述

通过复制一个已存在的对象来获得一个新的相同类型的对象被称作原型模式,在复制的过程中不需要关心被复制对象实现的接口或者类型

原型模式Prototype具有如下优点:

  • 隐藏了创建对象的实现细节
  • 复制操作不受子类构造器改变影响
  • 避免了重复创建对象产生的大量代码

简单来说,原型模式分为以下两种:

  • 简单拷贝
  • 登记拷贝

没有使用原型Prototype的拷贝代码是怎样的呢?我们需要通过访问

class Pet: NSObject {
    var name: String?
    var weigh: Float?

    init(name: String, weigh: Float) { ... }
}

class Person: NSObject {
    var pet: Pet?
    var name: String?
    var height: Float?

    init(name: String, height: Float, pet: Pet) { ... }
}

let pet = Pet(name: "球球", weigh: 2.0)
let author = Person(name: "林欣达", height: 173, pet: pet)
var persons: [Person] = [Person]()
for _ in 0...9 {
    persons.append(Person(name: author.name!, height: author.height!, pet: Pet(name: pet.name, weigh: pet.weigh)))
}

简单形式拷贝

通过声明一个Cloning协议来为需求方提供完全拷贝的方案

protocol Cloning {
    func clone() -> AnyObject
}

class Pet: NSObject, Cloning {
    func clone() -> AnyObject {
        return Pet(name: name!, weigh: weigh!)
    }
}

class Person: NSObject, Cloning {
    func clone() -> AnyObject {
        return Person(name: name!, height: height! pet: pet?.clone() as! Pet)
    }
}

let author = Person(name: "林欣达", height: 173, pet: Pet(name: "球球", weigh: 2.0))
var persons: [Person] = [Person]()
for _ in 0...9 {
    persons.append(author.clone())
}

简单点来说,原型模式在iOS开发中就是NSCopying协议,通过实现这个协议完成对象和其成员对象的完全内存拷贝,也可以称为深拷贝。从这个角度而言,原型模式Prototype就是深拷贝的理论化

登记拷贝

登记拷贝实际上就是在简单拷贝的基础之上对这些clone对象进行管理

class CloneManager: NSObject {
    static let sharedManager = CloneManager()
    private var mapper: [String: Cloning] = [String: Cloning]()

    private override init() {
        super.init()
    }

    func store(prototype: Cloning, for identifier: String) {
        mapper[identifier] = prototype
    }

    func prototype(for identifier: String) -> Cloning? {
        return mapper[identifier]
    }

    func remove(with identifier: String) {
        mapper[identifier] = nil
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        let clone = author.clone()
        CloneManager.sharedManager.store(clone, "CloneInstance")
        let storedClone = CloneManager.sharedManager.prototype(for: "CloneInstance")
        
        if clone == storedClone {
            print("Store success")
        }
        if clone != author {
            print("You create a copy instance of author")
        }

         CloneManager.sharedManager.remove(with: "CloneInstance")
          assert( CloneManager.sharedManager.prototype(for: "CloneInstance") == nil )
    }
}

总结

原型模式Prototype将对象和其成员对象的拷贝过程隐藏起来,只提供了一个简单的接口提供我们获取拷贝后的对象,是一种优雅而强大的设计。使用原型模式需要注意实现Cloning的对象其成员对象也应该遵循这个协议提供简单的拷贝接口