iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 8
0
自我挑戰組

Pro Design Patterns in Swift5系列 第 8

Day8: Prototype 模式(下)

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20200923/20130138y9SA4DzNaz.jpg

Photo by Gunnar Ridderström on Unsplash


程式列 5-8

import Foundation

class Person: NSObject, NSCopying {
    var name: String;
    var country: String;
    
    init(name: String, country: String) {
        self.name = name;
        self.country = country;
    }
    
    func copy(with zone: NSZone? = nil) -> Any {
        return Person(name: self.name, country: self.country);
    }
    
    func deepCopy(data: [AnyObject]) -> [AnyObject] {
        return data.map({ item -> AnyObject in
            if (item is NSCopying && item is NSObject) {
                return (item as! NSObject).copy() as AnyObject;
            } else {
                return item
            }
        })
    }
}

var people = [Person(name: "Joe", country: "France"), Person(name: "Bob", country: "USA")]

var otherPeople = people;
people[0].country = "UK";
print("Country: \(people[0].country)");

Any 和 AnyObject 的差別


程式列 5-9

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

func deepCopy(data: [AnyObject]) -> [AnyObject] {
    return data.map({ item -> AnyObject in
        if (item is NSCopying && item is NSObject) {
            return (item as! NSObject).copy() as AnyObject;
        } else {
            return item
        }
    })
}

var people = [Person(name: "Joe", country: "France"), Person(name: "Bob", country: "USA")]

var otherPeople = deepCopy(data: people) as! [Person];
people[0].country = "UK";
print("Country: \(people[0].country)");

// 程式列 5-11
class Sum: NSObject, NSCopying {
    
    var resultsCache: [[Int]];
    var firstValue: Int;
    var secondValue: Int;
    
    init(first:Int, second: Int) {
        resultsCache = [[Int]](repeating: ([Int](repeating: 0, count: 10)), count: 10);
        for i in 0..<10 {
            for j in 0..<10 {
                resultsCache[i][j] = i + j;
            }
        }
        
        self.firstValue = first;
        self.secondValue = second;
    }
    
    private init(first: Int, second: Int, cache: [[Int]]) {
        self.firstValue = first;
        self.secondValue = second;
        self.resultsCache = cache;
    }
    
    func copy(with zone: NSZone? = nil) -> Any {
        return Sum(first: self.firstValue, second: self.secondValue, cache: self.resultsCache)
    }
    
    var Result: Int {
        get {
            return firstValue < resultsCache.count
                && secondValue < resultsCache[firstValue].count
            ? resultsCache[firstValue][secondValue]
                : firstValue + secondValue;
        }
    }
}

var prototype = Sum(first: 0, second: 9);
var calc1 = prototype.Result;
var clone = prototype.copy() as! Sum;
clone.firstValue = 3;
clone.secondValue = 8;
var calc2 = clone.Result;

print("Calc1: \(calc1) Calc2 \(calc2)")

// 程式列 5-12

import Foundation

class Message {
    var to: String;
    var subject: String;
    
    init(to: String, subject: String) {
        self.to = to;
        self.subject = subject;
    }
}

class MessageLogger {
    var messages: [Message] = [];
    
    func logMessage(msg: Message) {
        messages.append(msg);
    }
    
    //MARK: callback: (Message) -> Void有這寫法? 有, 此招就是closures-as-parameters
    func processMessages(callback: (Message) -> Void) {
        for msg in messages {
            callback(msg);
        }
    }
}

var logger = MessageLogger();

var message = Message(to: "Joe", subject: "Hello");
logger.logMessage(msg: message);

message.to = "Bob";
message.subject = "Free for dinner?";
logger.logMessage(msg: message);

logger.processMessages(callback: { msg -> Void in
    print("Message - To: \(msg.to) Subject: \(msg.subject)");
});

closures-as-parameters


// 程式列 5-13 pass
// 程式列 5-14

class Message {
    var to: String;
    var subject: String;
    
    init(to: String, subject: String) {
        self.to = to;
        self.subject = subject;
    }
}

class DetailMessage: Message {
    var from: String;
    
    init(to: String, subject: String, from: String) {
        self.from = from;
        super.init(to: to, subject: subject)
    }
}

class MessageLogger {
    var messages: [Message] = [];
    
    func logMessage(msg: Message) {
        messages.append(Message(to: msg.to, subject: msg.subject));
    }

    func processMessages(callback: (Message) -> Void) {
        for msg in messages {
            callback(msg);
        }
    }
}

var logger = MessageLogger();

var message = Message(to: "Joe", subject: "Hello");
logger.logMessage(msg: message);

message.to = "Bob";
message.subject = "Free for dinner?";
logger.logMessage(msg: DetailMessage(to: "Alice", subject: "Hi", from: "Joe"));

logger.processMessages(callback: { msg -> Void in
    if let detail = msg as? DetailMessage {
        print("Detailed Message - To:\(detail.to) From: \(detail.from)" + "Subject: \(detail.subject)");
    } else {
        print("Message - To: \(msg.to) Subject: \(msg.subject)");
    }
});

程式列 5-15 pass
程式列 5-16 pass
程式列 5-17

import Foundation

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

var data = NSMutableArray(objects: 10, "iOS", Person(name: "Joe", country: "USA"))
var copiedData = data;

data[0] = 20;
data[1] = "MacOS";
(data[2] as! Person).name = "Alice"

print("Indentity: \(data === copiedData)");
//FIXME:
print("0: \(copiedData[0]) 1: \(copiedData[1]) 2: \((copiedData[2] as AnyObject).name)");

//TODO: study NSMutableArray


程式列 5-21 pass
程式列 5-22

import Foundation

class Logger<T> where T: NSObject, T:NSCopying {
    var dataItems:[T] = [];
    var callback:(T) -> Void;
    
    init(callback: @escaping (T) -> Void) {
        self.callback = callback;
    }
    
    func logItem(item: T) {
        dataItems.append(item.copy() as! T);
        callback(item);
    }
    
    func processItems(callback: @escaping (T) -> Void) {
        for item in dataItems {
            callback(item);
        }
    }
}

What is @escaping in Swift?

程式列 5-23 pass


結論
技術債越欠越多, 我要好好讀文件了

https://ithelp.ithome.com.tw/upload/images/20200923/201301387fbrERemBe.jpg

謝謝閱讀

Reference


上一篇
Day7: Prototype 模式(上)
下一篇
Day9: Chapter6: Singleton 模式(上)
系列文
Pro Design Patterns in Swift517
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言