协议中关联类型的依赖倒置
Dependency Inversion with assosiatedType in protocol
我很难尝试实现依赖倒置。环顾四周,找到一篇很棒的文章 Swift Type Erasure。我不确定如何才能在我的情况下获得优势。这就是我想要实现的目标。
网络协议
protocol Networkable {
associatedtype Response: Decodable
func request(handler: @escaping((Result<Response, Error>) -> ()))
}
Networkable
协议的具体实现
final class Networker<Response: Decodable>: Networkable {
private let session: URLSession
private let url: URL
init(session: URLSession, url: URL) {
self.session = session
self.url = url
}
func request(handler: @escaping ((Result<Response, Error>) -> ())) {
session.dataTask(with: url) { data, response, error in
handler(.success(try! JSONDecoder().decode(Response.self, from: data!)))
}
}
}
依赖于Networkable
协议的ViewModel
class ViewModel {
let networker: Networkable
// Error-> Protocol 'Networkable' can only be used as a generic constraint because it has Self or associated type requirements
init(netwrorker: Networkable) {
self.networker = netwrorker
}
func execute() {
networker.request { _ in
print("Responsed")
}
}
}
用法:
class View {
let viewModel: ViewModel
init() {
let networker = Networker<ResponseModel>(session: .shared, url: URL(string: "SOME URL")!)
self.viewModel = ViewModel(netwrorker: networker)
}
func load() {
viewModel.execute()
}
}
struct ResponseModel: Decodable {}
问题:
- 这是实现依赖倒置的正确方法吗?
- 如何在网络上实现通用行为 class 并且仍然开放测试?
您的 ViewModel
class 格式错误:
class ViewModel<T: Decodable> {
let networker: Networker<T>
…
}
否则你可能会创建一个类型擦除的 AnyNetworkable
具体类型,你可以像这样使用它:
class ViewModel<T: Decodable> {
let networker: AnyNetworkable<T>
…
}
或者您可以采用更通用的方法,如:
class ViewModel<R, T: Networkable> where T.Response == R {
let networker: T
}
显然,这同样反映在您的 View
类型上,您还需要针对 ViewModel
.
的特定具体类型进行通用或专门化
我很难尝试实现依赖倒置。环顾四周,找到一篇很棒的文章 Swift Type Erasure。我不确定如何才能在我的情况下获得优势。这就是我想要实现的目标。
网络协议
protocol Networkable {
associatedtype Response: Decodable
func request(handler: @escaping((Result<Response, Error>) -> ()))
}
Networkable
协议的具体实现
final class Networker<Response: Decodable>: Networkable {
private let session: URLSession
private let url: URL
init(session: URLSession, url: URL) {
self.session = session
self.url = url
}
func request(handler: @escaping ((Result<Response, Error>) -> ())) {
session.dataTask(with: url) { data, response, error in
handler(.success(try! JSONDecoder().decode(Response.self, from: data!)))
}
}
}
依赖于Networkable
协议的ViewModel
class ViewModel {
let networker: Networkable
// Error-> Protocol 'Networkable' can only be used as a generic constraint because it has Self or associated type requirements
init(netwrorker: Networkable) {
self.networker = netwrorker
}
func execute() {
networker.request { _ in
print("Responsed")
}
}
}
用法:
class View {
let viewModel: ViewModel
init() {
let networker = Networker<ResponseModel>(session: .shared, url: URL(string: "SOME URL")!)
self.viewModel = ViewModel(netwrorker: networker)
}
func load() {
viewModel.execute()
}
}
struct ResponseModel: Decodable {}
问题:
- 这是实现依赖倒置的正确方法吗?
- 如何在网络上实现通用行为 class 并且仍然开放测试?
您的 ViewModel
class 格式错误:
class ViewModel<T: Decodable> {
let networker: Networker<T>
…
}
否则你可能会创建一个类型擦除的 AnyNetworkable
具体类型,你可以像这样使用它:
class ViewModel<T: Decodable> {
let networker: AnyNetworkable<T>
…
}
或者您可以采用更通用的方法,如:
class ViewModel<R, T: Networkable> where T.Response == R {
let networker: T
}
显然,这同样反映在您的 View
类型上,您还需要针对 ViewModel
.