面向對象程序設計
(Object Oriented Programming)
其本質是以創建模型體現出來的抽象思惟過程和麪向對象的方法。模型是用來反映現實世界中事物特徵的。任何一個模型都不可能反映客觀事物的一切具體特徵,只能對事物特徵和變化規律的一種抽象,且在它所涉及的範圍內更廣泛、更集中、更深入地描述客體的特徵。經過創建模型而達到的抽象是人們對客體認識的深化python
正是由於化零爲整的功效,方便儲存數據而後傳輸! 面向對象的設計,在衆多語言裏面被採用!OC - Swift
主流方式也是 OOP
. 這個相比你們已經很是熟悉了,這裏也再也不囉嗦。今天的主角是 POP (Protocol Oriented Programming)
一 面向協議編程面試
面向對象的困境編程
王巍面向協議編程 這一篇文章裏面就有詳細表達!json
面向協議編程的思惟,在 Swift
開發中很是很是重要!能夠說若是你用好了 POP
那麼你的項目絕對逼格不是一個level
下面咱們經過解決 OOP
問題的思路展開分析api
POP 解決橫切關注點安全
橫切關注點(Cross-Cutting Concerns)
那就是咱們很難在不一樣繼承關係的類裏共用代碼! 如今咱們經過面向協議的方式,任何遵循協議的,均可以默認添加 name
屬性以及sayHello()
方法!bash
protocol LGProtocl {
/// 協議屬性
var name: String {get}
/// 協議方法
func sayHello()
}
複製代碼
WWDC 2015
和 Swift 2
發佈時,Apple
爲協議引入了一個新特性一 協議擴展 它爲 Swift 語言帶來了一次革命性的變化。struct LGTeacher: LGProtocl{
var name: String
func sayHello() {
print("你好")
}
}
複製代碼
這樣的操做有什麼做用了? 一 萬物皆 lg
網絡
// 聲明協議
extension LGCompatible {
/// Reactive extensions.
public static var lg: LGRxSwift.Reactive<Self>.Type
/// Reactive extensions.
public var lg: LGRxSwift.Reactive<Self>
}
// NSObject 實現
extension NSObject : LGCompatible { }
複製代碼
LGCompatible
引伸到Reactive
響應式類或者結構體Reactive
的能力,就能完美切合POP 解決動態派發安全性app
對於沒有實現 LGProtocl
的類型,編譯器將返回錯誤,所以不存在消息誤發送的狀況框架
// Compiler Error:
// 'LGTeacher' does not conform to protocol 'LGProtocl'
// protocol requires function 'sayHello()'
複製代碼
POP 解決菱形缺陷
最後咱們看看多繼承。多繼承中存在的一個重要問題是菱形缺陷,也就是子類沒法肯定使用哪一個父類的方法。在協議的對應方面,這個問題雖然依然存在,但倒是能夠惟一安全地肯定的。
這裏很遺憾POP在 解決菱形缺陷
這一點上也存在一樣的BUG , 由於多個協議存在相同的協議屬性、協議方法,遵循者也是沒法肯定的!⚠️ 咱們在平時開發中必定要儘可能規避同名協議遵循問題,咱們在模塊劃分上面必定要作作到完全,儘管 Swift 還不能很好地處理多個協議的衝突 可是咱們能夠在協議層功能抽層嚴格機智處理上浮與下沉功能。
舉個例子:🌰
咱們剛剛是否是作了LGCompatible
, 它是咱們功能的入口,萬物皆lg
,進來,那麼這層協議只須要提供入口就完畢
同時提供接口過分能力,把 LGReactiveCompatible
的 lg
過分到 Reactive
層
extension LGReactiveCompatible {
/// Reactive extensions.
public static var lg: Reactive<Self>.Type {
get { return Reactive<Self>.self }
set {// this enables using Reactive to "mutate" base type }
}
/// Reactive extensions.
public var lg: Reactive<Self> {
get { return Reactive(self) }
set { // this enables using Reactive to "mutate" base object }
}
}
複製代碼
Reactive
層, 根據業務劃分開來,達到邏輯代碼下沉效果!public struct Reactive<Base> {
public let base: Base
public init(_ base: Base) {
self.base = base
}
}
複製代碼
Reactive
裏面關聯的 Base
類型來肯定不一樣的響應式功能extension Reactive where Base: UISwitch
其中 UISwitch
能夠換成 UITableView、UITextField、UIView
... 不斷業務下沉!相信到這裏你已經感覺到了面向協議編程的方便之處,可是還有一個很是重要的特性沒有展示出來就是 一 耦合度大大下降,代碼分層,邏輯更清晰
咱們在實際開發中,網絡請求是一個很是重要的模塊
Alamofire.request("http://127.0.0.1:5000/pythonJson/")
.validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.responseData { response in
switch response.result {
case .success:
print(response)
let _ = LGLoginClient.lgJson(data: response.data)
case .failure(let error):
print(error)
}
}
複製代碼
ViewController
(表明應用層) 直接這麼網絡請求,耦合度是很是大的(應用層與網絡層耦合在一塊兒)method、接口、參數
說白了我也不想關心1️⃣:網絡信息能力
enum LGHTTPMethod: String {
case GET
case POST
}
protocol LGRequest {
var host: String { get }
var path: String { get }
var method: LGHTTPMethod { get }
var parameter: [String: Any] { get }
associatedtype Response
func parse(data: Data) -> Response?
}
複製代碼
LGHTTPMethod
提供本模塊LGRequest
須要的請求方法枚舉LGRequest
是登陸註冊模塊的請求能力賦予者,經過面向協議的方式給咱們的模塊提供能力Response
這個關聯類型,方便後面 json
轉模型,設置這個泛型類型是可以通用化2️⃣:模塊信息層
struct LGLoginRequest: LGRequest {
typealias Response = LGPerson
let name: String
let host = "http://127.0.0.1:5000"
var path: String {
return "/pythonJson/getTeacherInfo/?username=\(name)"
}
let method: LGHTTPMethod = .GET
let parameter: [String: Any] = [:]
func parse(data: Data) -> LGPerson? {
return LGPerson(data: data)
}
}
複製代碼
LGLoginRequest
遵循 LGRequest
得到host、path、method、parameter、parse
處理能力,在這裏能夠直接處理,就不須要到應用層再去傳值!3️⃣:網絡請求能力
extension LGRequest {
func send(handler: @escaping (Response?) -> Void) {
let url = URL(string: host.appending(path))!
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
let task = URLSession.shared.dataTask(with: request) {
data, response, error in
if let data = data, let res = self.parse(data: data) {
DispatchQueue.main.async { handler(res) }
} else {
DispatchQueue.main.async { handler(nil) }
}
}
task.resume()
}
}
複製代碼
Response
就是相應模型的具體類型4️⃣:應用層調用
override func viewDidLoad() {
super.viewDidLoad()
let request = LGPersonRequest(name: "Cooci")
request.send { (person) in
self.updataUI(person: person!)
}
}
複製代碼
LGPersonRequest
模塊信息處理提供層LGPersonRequest
同時還具有調用網絡能力5️⃣:POP網絡優化重構
很顯然咱們的 LGRequest
這個傢伙的能力太強了!能提供信息,還能發起請求,連序列化的處理能力也是由LGRequest
提供!優化重構迫在眉睫。。。。
1:信息提供能力者
protocol LGRequest {
var path: String { get }
var method: LGHTTPMethod { get }
var parameter: [String: Any] { get }
associatedtype Response: LGDecodable
}
struct LGPersonRequest: LGRequest {
typealias Response = LGPerson
let name: String
var path: String {
return "/pythonJson/getTeacherInfo/?username=\(name)"
}
let method: LGHTTPMethod = .GET
let parameter: [String: Any] = [:]
}
複製代碼
host
提取出去LGRequest
網絡請求能力LGDecodable
protocol ClientProtocol {
var host: String { get }
func send<T: LGRequest>(_ r: T, handler: @escaping (T.Response?) -> Void)
}
class LGClient: ClientProtocol{
static let manager = LGClient()
let host: String = "http://127.0.0.1:5000"
func send<T>(_ r: T, handler: @escaping (T.Response?) -> Void) where T : LGRequest {
let url = URL(string: host.appending(r.path))!
var request = URLRequest(url: url)
request.httpMethod = r.method.rawValue
let task = URLSession.shared.dataTask(with: request) {
data, response, error in
if let data = data, let res = T.Response.parse(data: data) {
DispatchQueue.main.async { handler(res) }
} else {
DispatchQueue.main.async { handler(nil) }
}
}
task.resume()
}
}
複製代碼
LGClient
2:網絡能力提供者
class LGLoginClient: LGClient {
override func send<T>(_ r: T, handler: @escaping (T.Response?) -> Void) where T : LGRequest {
switch r.path {
case let string where string.contains("/pythonJson/getTeacherInfo"):
print("123456")
handler(nil)
default:
let url = URL(string: host.appending(r.path))!
var request = URLRequest(url: url)
request.httpMethod = r.method.rawValue
let task = URLSession.shared.dataTask(with: request) {
data, response, error in
if let data = data, let res = T.Response.parse(data: data) {
DispatchQueue.main.async { handler(res) }
} else {
DispatchQueue.main.async { handler(nil) }
}
}
task.resume()
}
}
}
複製代碼
LGLoginClient
重寫,根據不一樣的接口分塊處理T.Response
) 處理3:序列化能力提供層
extension LGPerson: LGDecodable {
static func parse(data: Data) -> LGPerson? {
return LGPerson(data: data)
}
}
複製代碼
6️⃣:小結
POP
網絡編程 那麼我估計你須要好好學習咯!💪💪💪最近有從朋友那裏拿到一些iOS面試題總結的pdf文檔!由於平臺不能發送文件,須要的朋友能夠添加QQ羣:679884541,羣裏面都是iOS開發者,有什麼問題和牢騷你們一塊兒交流吧!