Swift设计模式(二)原型模式

应用场景:
需要通过复制对象达到创建新对象的目的。
难点:深拷贝和浅拷贝

初始化一个类或者结构体会消耗大量的内存资源和计算资源,然而通过拷贝是可以节省这些资源的。
值类型的拷贝都是深拷贝,不必多言。
那么如何对引用类型实现深拷贝呢?
答案就是NSCopying协议

class ProductA: NSCopying {
    var name: String
    var price: Int
    init(name:String,price:Int) {
        self.name = name
        self.price = price
    }
    func copy(with zone: NSZone? = nil) -> Any {
        return ProductA.init(name: self.name, price: self.price)
    }
}
        let p = ProductA.init(name: "book", price: 10)
        let c = p.copy() as! ProductA
        c.name = "computer"

        print(c.name,p.name)

在swift4中你可以暂时忽略zone

那么引用类型中包含引用类型的拷贝呢?

copy(with zone: NSZone? = nil)

只是拷贝的对象的引用,而不是对象的本身,也就会浅拷贝:

class ProductA: NSCopying {
    var name: String
    var price: Int
    var place: PlaceOfOrigin

    init(name:String,price:Int, place:PlaceOfOrigin) {
        self.name = name
        self.price = price
        self.place = place
    }
    func copy(with zone: NSZone? = nil) -> Any {
        return ProductA.init(name: self.name, price: self.price,place:self.place)
    }
}

class PlaceOfOrigin{
    var country: String
    var city: String
    init(country:String, city:String) {
        self.country = country
        self.city = city
    }

}
let p = ProductA.init(name: "book", price: 10, place: PlaceOfOrigin.init(country: "American", city: "NewYork"))
        let c = p.copy() as! ProductA
        c.name = "computer"
        c.place.city = "BeiJing"
        print(c.name,c.place.city,p.name,p.place.city)

//log::: computer BeiJing book BeiJing

那么如何更改呢?

class ProductA: NSCopying {
    var name: String
    var price: Int
    var place: PlaceOfOrigin

    init(name:String,price:Int, place:PlaceOfOrigin) {
        self.name = name
        self.price = price
        self.place = place
    }
    func copy(with zone: NSZone? = nil) -> Any {
        return ProductA.init(name: self.name, price: self.price,place:self.place.copy() as! PlaceOfOrigin)
    }
}

class PlaceOfOrigin:NSCopying{
    var country: String
    var city: String
    init(country:String, city:String) {
        self.country = country
        self.city = city
    }
    func copy(with zone: NSZone? = nil) -> Any {
        return PlaceOfOrigin.init(country: self.country, city: self.city)
    }
}

///log:::: computer BeiJing book NewYork

下面,我们来看数组复制

    var productAs = [ProductA.init(name: "computer", price: 10000, place: PlaceOfOrigin.init(country: "China", city: "BeiJing"))]

    func testArray(){
        let otherProducts = self.productAs
        otherProducts[0].name = "hh"

        print(productAs[0].name,otherProducts[0].name)
    }

///log: hh hh

ok 我们看到是浅拷贝,那么如何进行深拷贝呢?

let otherProducts =  productAs.map { (p) -> ProductA in
            return p.copy() as! ProductA
        }
        otherProducts[0].name = "hh"
        print(otherProducts[0].name)
        print(productAs[0].name)

//log : hh computer

使用原型模式,有几个陷阱
1.深复制与潜复制
2.记住可以以克隆的副本,作为下一次的原型

你可能感兴趣的:(设计模式)