日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

Swift 中的设计模式 #3 外观模式与适配器模式

發布時間:2023/12/15 asp.net 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Swift 中的设计模式 #3 外观模式与适配器模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:Andrew Jaffee,原文鏈接,原文日期:2018-09-04 譯者:鄭一一;校對:BigNerdCoding,pmst,Forelax;定稿:Forelax

本文是我的設計模式系列教程的第三篇。在第一篇文章中,我介紹了 創建型模式中的工廠模式和單例模式。在第二篇文章中,又討論了一下 行為型模式中的觀察者模式和備忘錄模式。

在本文中,我會就結構型模式中的外觀模式適配器模式分別舉一個例子。首先,我建議你先去閱讀前面提到的兩篇文章,這會有助于你更熟悉軟件設計模式的一些概念。除了簡短地介紹一下設計模式的組成,我不會再重復介紹所有關于設計模式的概念了。如果需要了解,都可以在前面寫的 第一篇第二篇 中找到。

接下來的幾節,我們先來簡單回顧一下設計模式的通用概念。“Gang of Four” (“GoF”) Erich Gamma,Richard Helm,Ralph Johonson,和 John Vlissides 在他們“設計模式:面向對象軟件設計復用的基本原理”的重要著作里整理了 23 種經典的設計模式。今天我們重點關注的是兩種結構型設計模式:外觀模式適配器模式

值語義的面向協議編程

你可能會發現世面上非常多設計模式教程的示例代碼,仍然是基于面向對象編程原則(OOP)、引用語義和 引用類型(classes)編寫的。所以,我決定編寫一套基于 面向協議編程原則(POP)、值語義和 值類型(structs)的設計模式系列教程。如果你已經看過了我之前寫的兩篇文章,我希望你還能夠熟悉一下 OOP 和 POP,引用語義和值語義這些概念。如果你還不是特別熟悉,我強烈建議趕緊去了解一下這些主題。本文所舉的例子是全部基于 POP 和值語義的。

設計模式

設計模式是開發者用于管理軟件復雜性極其重要的工具。作為常見的模板技術,它很好地對軟件中類似的、重復出現的、容易識別的問題進行了概念化抽象。我們可以將它視作最佳實踐,從而應用到日常中會遇到的那些編程場景中。舉一個具體的例子,回想一下你在平常寫代碼過程中有多少次會使用或寫了遵守 觀察者設計模式 的代碼吧。

在觀察者模式中,被觀察者(一般來說是一個關鍵資源)會給所有依賴于自己的觀察者,廣播通知其內部狀態的變化。觀察者必須告知被觀察者自己想接收通知,換句話說,觀察者必須訂閱通知。用戶授權的 iOS 彈窗推送通知,就是一個典型的觀察者模式的例子。

設計模式的分類

GoF 將 23 種設計模式歸納為三種類型,分別是“創建型”、“行為型”、“結構型”。本文會介紹兩種結構型設計模式。先看一下結構這個詞的定義:

“以一種確定方式構建的事物以及實體中各部分元素之間不同關系的匯總。” - www.merriam-webster.com/dictionary/…

結構型設計模式的主要作用是明確一段代碼的功能,并說明如何使用。大部分的結構型設計模式可以通過編寫易讀接口,來實現對一段代碼的簡化使用。因為一段代碼勢必要與其它代碼聯系,如果要為代碼段編寫出良好的接口,必須明確清晰地定義代碼之間的各種關系。

外觀設計模式

“外觀可以定義為特殊結構化的建筑物表面或者錯誤的、表面上的、人為的外形或效果”。 - www.merriam-webster.com/dictionary/…

大部分情況下,可以使用外觀模式,為一組復雜接口創建一個簡單接口。或許你已經寫過“封裝”代碼。“封裝”的意思就是對一段復雜代碼的簡化使用。

外觀設計模式的示例 app

外觀設計模式示例的 playground 文件,可以在 GitHub 找到。在這個例子里展示了,如何通過外觀設計模式,來為沙盒文件系統創建一個簡單的接口,供所有的 iOS app 使用。iOS 文件系統是一個龐大的操作系統子系統,功能包括創建、讀取、刪除、移動、重命名、拷貝文件和目錄。允許獲取和設置文件和目錄的元數據,比如列出在指定目錄下的所有文件。允許查看文件和目錄的狀態,比如某個指定文件是否可寫。提供蘋果推薦、預定義的目錄名。實際上其包含的功能遠遠不止上面提到的這些。

由于 iOS 文件系統是一個擁有如此多特性和功能的宏大主題,因此也是一個非常好的例子,用來講解如何通過外觀設計模式來簡化代碼的使用。外觀接口會廢棄掉無關功能和雜亂代碼的部分。另一方面,外觀接口只會定義在某個具體 app 需要使用到的功能。或者在我的例子中,我將功能縮減到只有經常使用的那部分。這樣做的好處是保證代碼在不同 app 中都是可復用、可擴展,可維護的。

基于面向協議編程和值語義,我將 iOS 文件系統的主要特性進行了劃分,從而將其變成可復用、可擴展的單元:協議和協議擴展。

將四個協議組合成一個結構體,這個結構體代表了可以在所有 iOS 應用中使用的沙盒 iOS 目錄(還可以看 這篇文章)。因為未來你肯定會更多接觸到更多面向協議編程和值語義相關的主題,要注意術語 composedcomposition 在這里屬于同義詞。

除此之外,為了讓你更專注于理解外觀設計模式的使用,在后面的代碼中,我省略了 Swift 錯誤處理和通用錯誤檢查的代碼。

外觀設計模式的示例代碼

接下來就看看我的代碼吧。先確保已經下載了我在 GitHub 上的 playground 文件。下面是蘋果官方推薦的用于文件系統操作的預定義目錄。

enum AppDirectories : String {case Documents = "Documents"case Inbox = "Inbox"case Library = "Library"case Temp = "tmp" } 復制代碼

通過將文件操作限定在上述目錄中,避免了復雜性,并遵循了人機界面指南的原則。

在探究文件操作的核心代碼之前,先來看看使用外觀設計模式所設計出來的接口吧。我創建了 iOSAppFileSystemDirectory 結構體,作為文件系統常用功能的簡單可讀接口。這個接口適用于 AppDirectories 枚舉下的所有目錄。事實上,我原本還可以加入諸如 符號化鏈接的創建,或者使用 FileHandle 類實現對文件的精細控制。但是在實際情況中,我幾乎不太使用到這些功能,更重要的一點是,我想要保持代碼的簡潔性。

我創建了由四個協議組成的外觀。(我知道你看到下面的代碼中只遵循了三個協議,這其實是因為其中有一個協議繼承自另一個協議):

struct iOSAppFileSystemDirectory : AppFileManipulation, AppFileStatusChecking, AppFileSystemMetaData {let workingDirectory: AppDirectoriesinit(using directory: AppDirectories) {self.workingDirectory = directory}func writeFile(containing text: String, withName name: String) -> Bool {return writeFile(containing: text, to: workingDirectory, withName: name)}func readFile(withName name: String) -> String {return readFile(at: workingDirectory, withName: name)}func deleteFile(withName name: String) -> Bool {return deleteFile(at: workingDirectory, withName: name)}func showAttributes(forFile named: String) -> Void {let fullPath = buildFullPath(forFileName: named, inDirectory: workingDirectory)let fileAttributes = attributes(ofFile: fullPath)for attribute in fileAttributes {print(attribute)}}func list() {list(directory: getURL(for: workingDirectory))}} // 完成結構體 iOSAppFileSystemDirectory 的定義 復制代碼

下面是一些用于測試 iOSAppFileSystemDirectory 結構體的代碼:

var iOSDocumentsDirectory = iOSAppFileSystemDirectory(using: .Documents)iOSDocumentsDirectory.writeFile(containing: "New file created.", withName: "myFile3.txt") iOSDocumentsDirectory.list() iOSDocumentsDirectory.readFile(withName: "myFile3.txt") iOSDocumentsDirectory.showAttributes(forFile: "myFile3.txt") iOSDocumentsDirectory.deleteFile(withName: "myFile3.txt") 復制代碼

接下來的代碼是在運行了 playground 文件中代碼之后的控制臺輸出:

---------------------------- LISTING: /var/folders/5_/kd8__nv1139__dq_3nfvsmhh0000gp/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.Swift-Facade-Design-Pattern-1C4BD3E3-E23C-4991-A344-775D5585D1D7/DocumentsFile: "myFile3.txt" File: "Shared Playground Data"----------------------------File created with contents: New file created.(key: __C.FileAttributeKey(_rawValue: NSFileType), value: NSFileTypeRegular) (key: __C.FileAttributeKey(_rawValue: NSFilePosixPermissions), value: 420) (key: __C.FileAttributeKey(_rawValue: NSFileSystemNumber), value: 16777223) (key: __C.FileAttributeKey(_rawValue: NSFileExtendedAttributes), value: {"com.apple.quarantine" = <30303836 3b356238 36656364 373b5377 69667420 46616361 64652044 65736967 6e205061 74746572 6e3b>; }) (key: __C.FileAttributeKey(_rawValue: NSFileReferenceCount), value: 1) (key: __C.FileAttributeKey(_rawValue: NSFileSystemFileNumber), value: 24946094) (key: __C.FileAttributeKey(_rawValue: NSFileGroupOwnerAccountID), value: 20) (key: __C.FileAttributeKey(_rawValue: NSFileModificationDate), value: 2018-08-29 18:58:31 +0000) (key: __C.FileAttributeKey(_rawValue: NSFileCreationDate), value: 2018-08-29 18:58:31 +0000) (key: __C.FileAttributeKey(_rawValue: NSFileSize), value: 17) (key: __C.FileAttributeKey(_rawValue: NSFileExtensionHidden), value: 0) (key: __C.FileAttributeKey(_rawValue: NSFileOwnerAccountID), value: 502)File deleted. 復制代碼

我們來簡單討論下 iOSAppFileSystemDirectory 結構體所遵循的幾個協議。AppDirectoryNames 協議和擴展定義和實現了以 URL 類型獲取 AppDirectories 枚舉中目錄完整路徑的方法。

protocol AppDirectoryNames {func documentsDirectoryURL() -> URLfunc inboxDirectoryURL() -> URLfunc libraryDirectoryURL() -> URLfunc tempDirectoryURL() -> URLfunc getURL(for directory: AppDirectories) -> URLfunc buildFullPath(forFileName name: String, inDirectory directory: AppDirectories) -> URL} // end protocol AppDirectoryNamesextension AppDirectoryNames {func documentsDirectoryURL() -> URL {return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!}func inboxDirectoryURL() -> URL {return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent(AppDirectories.Inbox.rawValue) // "Inbox")}func libraryDirectoryURL() -> URL {return FileManager.default.urls(for: FileManager.SearchPathDirectory.libraryDirectory, in: .userDomainMask).first!}func tempDirectoryURL() -> URL {return FileManager.default.temporaryDirectory//urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent(AppDirectories.Temp.rawValue) //"tmp")}func getURL(for directory: AppDirectories) -> URL {switch directory {case .Documents:return documentsDirectoryURL()case .Inbox:return inboxDirectoryURL()case .Library:return libraryDirectoryURL()case .Temp:return tempDirectoryURL()}}func buildFullPath(forFileName name: String, inDirectory directory: AppDirectories) -> URL {return getURL(for: directory).appendingPathComponent(name)} } // end extension AppDirectoryNames 復制代碼

AppFileStatusChecking 協議和擴展封裝了獲取文件狀態數據的方法。這些文件同樣存儲于 AppDirectories 枚舉定義下的目錄。通過“狀態”,可以確定某個文件是否存在,是否可讀等。

protocol AppFileStatusChecking {func isWritable(file at: URL) -> Boolfunc isReadable(file at: URL) -> Boolfunc exists(file at: URL) -> Bool }extension AppFileStatusChecking {func isWritable(file at: URL) -> Bool {if FileManager.default.isWritableFile(atPath: at.path) {print(at.path)return true}else {print(at.path)return false}}func isReadable(file at: URL) -> Bool {if FileManager.default.isReadableFile(atPath: at.path) {print(at.path)return true}else {print(at.path)return false}}func exists(file at: URL) -> Bool {if FileManager.default.fileExists(atPath: at.path) {return true}else {return false}} } // end extension AppFileStatusChecking 復制代碼

AppFileSystemMetaData 協議和擴展實現了列出目錄內容和獲取擴展文件的功能。 其目錄也是定義在 AppDirectories 枚舉下。

protocol AppFileSystemMetaData {func list(directory at: URL) -> Boolfunc attributes(ofFile atFullPath: URL) -> [FileAttributeKey : Any] }extension AppFileSystemMetaData {func list(directory at: URL) -> Bool {let listing = try! FileManager.default.contentsOfDirectory(atPath: at.path)if listing.count > 0 {print("\n----------------------------")print("LISTING: \(at.path)")print("")for file in listing {print("File: \(file.debugDescription)")}print("")print("----------------------------\n")return true}else {return false}}func attributes(ofFile atFullPath: URL) -> [FileAttributeKey : Any] {return try! FileManager.default.attributesOfItem(atPath: atFullPath.path)} } // end extension AppFileSystemMetaData 復制代碼

最后是 AppFileManipulation 協議和擴展,封裝了 AppDirectories 枚舉目錄下的所有文件操作方法,包括了讀、寫、刪除、重命名、移動、拷貝修改文件擴展名等。

protocol AppFileManipulation : AppDirectoryNames {func writeFile(containing: String, to path: AppDirectories, withName name: String) -> Boolfunc readFile(at path: AppDirectories, withName name: String) -> Stringfunc deleteFile(at path: AppDirectories, withName name: String) -> Boolfunc renameFile(at path: AppDirectories, with oldName: String, to newName: String) -> Boolfunc moveFile(withName name: String, inDirectory: AppDirectories, toDirectory directory: AppDirectories) -> Boolfunc copyFile(withName name: String, inDirectory: AppDirectories, toDirectory directory: AppDirectories) -> Boolfunc changeFileExtension(withName name: String, inDirectory: AppDirectories, toNewExtension newExtension: String) -> Bool }extension AppFileManipulation {func writeFile(containing: String, to path: AppDirectories, withName name: String) -> Bool {let filePath = getURL(for: path).path + "/" + namelet rawData: Data? = containing.data(using: .utf8)return FileManager.default.createFile(atPath: filePath, contents: rawData, attributes: nil)}func readFile(at path: AppDirectories, withName name: String) -> String {let filePath = getURL(for: path).path + "/" + namelet fileContents = FileManager.default.contents(atPath: filePath)let fileContentsAsString = String(bytes: fileContents!, encoding: .utf8)print("File created with contents: \(fileContentsAsString!)\n")return fileContentsAsString!}func deleteFile(at path: AppDirectories, withName name: String) -> Bool {let filePath = buildFullPath(forFileName: name, inDirectory: path)try! FileManager.default.removeItem(at: filePath)print("\nFile deleted.\n")return true}func renameFile(at path: AppDirectories, with oldName: String, to newName: String) -> Bool {let oldPath = getURL(for: path).appendingPathComponent(oldName)let newPath = getURL(for: path).appendingPathComponent(newName)try! FileManager.default.moveItem(at: oldPath, to: newPath)// highlights the limitations of using return valuesreturn true}func moveFile(withName name: String, inDirectory: AppDirectories, toDirectory directory: AppDirectories) -> Bool {let originURL = buildFullPath(forFileName: name, inDirectory: inDirectory)let destinationURL = buildFullPath(forFileName: name, inDirectory: directory)// warning: constant 'success' inferred to have type '()', which may be unexpected// *let success =*try! FileManager.default.moveItem(at: originURL, to: destinationURL)return true}func copyFile(withName name: String, inDirectory: AppDirectories, toDirectory directory: AppDirectories) -> Bool {let originURL = buildFullPath(forFileName: name, inDirectory: inDirectory)let destinationURL = buildFullPath(forFileName: name, inDirectory: directory)try! FileManager.default.copyItem(at: originURL, to: destinationURL)return true}func changeFileExtension(withName name: String, inDirectory: AppDirectories, toNewExtension newExtension: String) -> Bool {var newFileName = NSString(string:name)newFileName = newFileName.deletingPathExtension as NSStringnewFileName = (newFileName.appendingPathExtension(newExtension) as NSString?)!let finalFileName:String = String(newFileName)let originURL = buildFullPath(forFileName: name, inDirectory: inDirectory)let destinationURL = buildFullPath(forFileName: finalFileName, inDirectory: inDirectory)try! FileManager.default.moveItem(at: originURL, to: destinationURL)return true} } // end extension AppFileManipulation 復制代碼

適配器設計模式

“適配”的含義是“通過修改讓一個事物更適合(用于新用途)。” - www.merriam-webster.com/dictionary/…

“適配器”的含義是“用于適配不在初始使用意圖范圍內設備的一種附加裝置。” - www.merriam-webster.com/dictionary/…

適配器設計模式的作用是在不修改已有代碼庫 "A" 的前提下,仍舊可以使用與代碼庫 "A" 不兼容的代碼庫 "B",并保證 "A" 可以正常工作。我們可以創建適配器來保證 "A" 和 "B" 可以一起工作。其中一定要牢記的原則是代碼庫 "A" 是不能被修改的。(這是因為修改會破壞原有代碼或者我們根本就沒有這段源代碼)

適配器設計模式示例 app

適配器的 playground 文件,可以在 GitHub 上找到。在這部分代碼中,我們基于 iOS 文件系統進行適配器模式的討論,并基于 iOS 文件系統設計了一個適配器模式的例子。之前一章,我們已經實現了將 iOS 文件系統中所有目錄和文件的路徑表示為 URL 實例。想象一下下面的場景,在原有工程中已經存在了大量關于 iOS 文件系統的代碼,但是所有目錄和文件的路徑都表示成了字符串形式。那我們就必須要讓基于 URL 和基于 String 的代碼可以協同工作。

適配器設計模式的示例代碼

接下來就看看代碼吧。先確保已經下載了在 GitHub 上的 playground 文件。為了在接下來的分析中更加專注于適配器模式的討論,下面會使用簡化版本的 AppDirectories 枚舉和 AppDirectoryNames 協議和擴展。

enum AppDirectories : String {case Documents = "Documents"case Temp = "tmp" }protocol AppDirectoryNames {func documentsDirectoryURL() -> URLfunc tempDirectoryURL() -> URL }extension AppDirectoryNames {func documentsDirectoryURL() -> URL {return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!}func tempDirectoryURL() -> URL {return FileManager.default.temporaryDirectory} } 復制代碼

一種方法是創建一個“專用”適配器。這個適配器會返回字符串路徑,這些路徑全部歸屬于在 AppDirectories 下的目錄和文件。

// 專用適配器 struct iOSFile : AppDirectoryNames {let fileName: URLvar fullPathInDocuments: String {return documentsDirectoryURL().appendingPathComponent(fileName.absoluteString).path}var fullPathInTemporary: String {return tempDirectoryURL().appendingPathComponent(fileName.absoluteString).path}var documentsStringPath: String {return documentsDirectoryURL().path}var temporaryStringPath: String {return tempDirectoryURL().path}init(fileName: String) {self.fileName = URL(string: fileName)!} } 復制代碼

下一部分是用于測試 iOSFile “專用”適配器的代碼,請注意代碼中的注釋。

let iOSfile = iOSFile(fileName: "myFile.txt") iOSfile.fullPathInDocuments iOSfile.documentsStringPathiOSfile.fullPathInTemporary iOSfile.temporaryStringPath// 通過 `AppDirectoryNames` 協議,仍然能夠訪問到 URL iOSfile.documentsDirectoryURL() iOSfile.tempDirectoryURL() 復制代碼

最后是 playground 文件中每一行代碼對應的右側輸出,這些輸出代表了運行時每一行代碼的值。參照上一段代碼,我們可以進行逐行對照。

iOSFile "/var/folders/5_/kd8__nv1139__dq_3nfvsmhh0000gp/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.Swift-Adapter-Design-Pattern-0A71F81A-9388-41F5-ACBE-52A1A61A9B99/Documents/myFile.txt" "/var/folders/5_/kd8__nv1139__dq_3nfvsmhh0000gp/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.Swift-Adapter-Design-Pattern-0A71F81A-9388-41F5-ACBE-52A1A61A9B99/Documents""/Users/softwaretesting/Library/Developer/XCPGDevices/52E1A81A-98AF-42DE-ADCF-E69AC8FA2791/data/Containers/Data/Application/F08EFF4F-8C4F-4BB7-B220-980E16344F18/tmp/myFile.txt" "/Users/softwaretesting/Library/Developer/XCPGDevices/52E1A81A-98AF-42DE-ADCF-E69AC8FA2791/data/Containers/Data/Application/F08EFF4F-8C4F-4BB7-B220-980E16344F18/tmp"file:///var/folders/5_/kd8__nv1139__dq_3nfvsmhh0000gp/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.Swift-Adapter-Design-Pattern-0A71F81A-9388-41F5-ACBE-52A1A61A9B99/Documents/ file:///Users/softwaretesting/Library/Developer/XCPGDevices/52E1A81A-98AF-42DE-ADCF-E69AC8FA2791/data/Containers/Data/Application/F08EFF4F-8C4F-4BB7-B220-980E16344F18/tmp/ 復制代碼

另外,我還傾向為字符串類型的路徑設計一個適配器協議。這樣就可以很方便地使用字符串路徑來替代 URL 路徑。

// Protocol-oriented approach protocol AppDirectoryAndFileStringPathNamesAdpater : AppDirectoryNames {var fileName: String { get }var workingDirectory: AppDirectories { get }func documentsDirectoryStringPath() -> Stringfunc tempDirectoryStringPath() -> Stringfunc fullPath() -> String} // end protocol AppDirectoryAndFileStringPathAdpaterNamesextension AppDirectoryAndFileStringPathNamesAdpater {func documentsDirectoryStringPath() -> String {return documentsDirectoryURL().path}func tempDirectoryStringPath() -> String {return tempDirectoryURL().path}func fullPath() -> String {switch workingDirectory {case .Documents:return documentsDirectoryStringPath() + "/" + fileNamecase .Temp:return tempDirectoryStringPath() + "/" + fileName}}} // end extension AppDirectoryAndFileStringPathNamesAdpaterstruct AppDirectoryAndFileStringPathNames : AppDirectoryAndFileStringPathNamesAdpater {let fileName: Stringlet workingDirectory: AppDirectoriesinit(fileName: String, workingDirectory: AppDirectories) {self.fileName = fileNameself.workingDirectory = workingDirectory}} // end struct AppDirectoryAndFileStringPathNames 復制代碼

接下來是用于測試 AppDirectoryAndFileStringPathNames 結構體的代碼。這個結構體遵守了 AppDirectoryAndFileStringPathNamesAdpater 適配器協議。協議繼承自 AppDirectoryNames 協議。注意在代碼中的兩段注釋。

let appFileDocumentsDirectoryPaths = AppDirectoryAndFileStringPathNames(fileName: "myFile.txt", workingDirectory: .Documents) appFileDocumentsDirectoryPaths.fullPath() appFileDocumentsDirectoryPaths.documentsDirectoryStringPath()// 通過 `AppDirectoryNames` 協議仍然可以訪問 URL appFileDocumentsDirectoryPaths.documentsDirectoryURL()let appFileTemporaryDirectoryPaths = AppDirectoryAndFileStringPathNames(fileName: "tempFile.txt", workingDirectory: .Temp) appFileTemporaryDirectoryPaths.fullPath() appFileTemporaryDirectoryPaths.tempDirectoryStringPath()// 通過 `AppDirectoryNames` 協議仍然可以訪問 URL appFileTemporaryDirectoryPaths.tempDirectoryURL() 復制代碼

最后是在 playground 文件中右側的輸出。每一行代表了運行時的代碼值,下面的輸出同樣和上一段代碼是逐行對應的。

AppDirectoryAndFileStringPathNames "/var/folders/5_/kd8__nv1139__dq_3nfvsmhh0000gp/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.Swift-Adapter-Design-Pattern-A3DE7CC8-D60F-4448-869F-2A19556C62B2/Documents/myFile.txt" "/var/folders/5_/kd8__nv1139__dq_3nfvsmhh0000gp/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.Swift-Adapter-Design-Pattern-A3DE7CC8-D60F-4448-869F-2A19556C62B2/Documents"file:///var/folders/5_/kd8__nv1139__dq_3nfvsmhh0000gp/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.Swift-Adapter-Design-Pattern-A3DE7CC8-D60F-4448-869F-2A19556C62B2/Documents/AppDirectoryAndFileStringPathNames "/Users/softwaretesting/Library/Developer/XCPGDevices/52E1A81A-98AF-42DE-ADCF-E69AC8FA2791/data/Containers/Data/Application/CF3D4156-E773-4BC4-B117-E7BDEFA3F34C/tmp/tempFile.txt" "/Users/softwaretesting/Library/Developer/XCPGDevices/52E1A81A-98AF-42DE-ADCF-E69AC8FA2791/data/Containers/Data/Application/CF3D4156-E773-4BC4-B117-E7BDEFA3F34C/tmp"file:///Users/softwaretesting/Library/Developer/XCPGDevices/52E1A81A-98AF-42DE-ADCF-E69AC8FA2791/data/Containers/Data/Application/CF3D4156-E773-4BC4-B117-E7BDEFA3F34C/tmp/ 復制代碼

結論

設計模式不僅有利于代碼復用,還能保證代碼是不變、易讀、松耦合的,從而提高了可維護性和拓展性。當重復出現并且能加以抽象的功能在你的 app 中出現的時候,我希望你能應用一下設計模式,并 封裝進框架 中。這樣子你只需要寫一次代碼,就可以一直復用啦。

再次感謝大家來 AppCoda 給我捧場。享受工作,堅持學習,下次再見吧!

本文由 SwiftGG 翻譯組翻譯,已經獲得作者翻譯授權,最新文章請訪問 swift.gg。

總結

以上是生活随笔為你收集整理的Swift 中的设计模式 #3 外观模式与适配器模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。