面向对象程序设计
(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开发者,有什么问题和牢骚你们一块儿交流吧!