Created
July 7, 2019 09:58
-
-
Save ppth0608/03bba7ee850d8362458012af8c62d042 to your computer and use it in GitHub Desktop.
How to implement `DI(Dependency Injection)` with `Service` pattern
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol ServiceProviderType { | |
var clipService: ClipServiceType { get } | |
} | |
class ServiceProvider: ServiceProviderType { | |
lazy var clipService: ClipServiceType = ClipService(provider: self, clipAPI: ClipAPI()) | |
} | |
protocol ServiceType { | |
var provider: ServiceProvider { get set } | |
} | |
class Service: ServiceType { | |
unowned var provider: ServiceProvider | |
init(provider: ServiceProvider) { | |
self.provider = provider | |
} | |
} | |
protocol ClipServiceType: ServiceType { | |
func recentClips(keyword: String) -> Observable<[Clip]> | |
func clips(for category: ClipCategory) -> Observable<[Clip]> | |
func add(with clip: Clip) -> Observable<Clip> | |
func remove(at clip: Clip) -> Observable<Clip> | |
func bookmark(with clip: Clip) -> Observable<Clip> | |
} | |
class ClipService: Service, ClipServiceType { | |
let clipAPI: ClipAPIType | |
init(provider: ServiceProvider, clipAPI: ClipAPIType) { | |
self.clipAPI = clipAPI | |
super.init(provider: provider) | |
} | |
func recentClips(keyword: String) -> Observable<[Clip]> { | |
return clipAPI | |
.recentClips(keyword: keyword) | |
.catchErrorJustReturn([]) | |
} | |
func clips(for category: ClipCategory) -> Observable<[Clip]> { | |
return clipAPI | |
.clips(for: category) | |
.catchErrorJustReturn([]) | |
} | |
func add(with clip: Clip) -> Observable<Clip> { | |
return clipAPI | |
.add(with: clip) | |
} | |
func remove(at clip: Clip) -> Observable<Clip> { | |
return clipAPI | |
.remove(at: clip) | |
.map { _ in clip } | |
} | |
func bookmark(with clip: Clip) -> Observable<Clip> { | |
return clipAPI | |
.bookmark(with: clip) | |
.catchErrorJustReturn(clip) | |
} | |
} | |
public protocol ClipAPIType { | |
/// Fetch recent clip list | |
/// - Parameter keyword: `Title` or `User-defiend Title` is search keawork | |
func recentClips(keyword: String) -> Observable<[Clip]> | |
/// Fetch only clip lists in a specific category of the entire clip list | |
/// - Parameter for: Specific category | |
func clips(for category: ClipCategory) -> Observable<[Clip]> | |
/// Add clip | |
/// - Parameter with: Target `Clip` to add | |
func add(with clip: Clip) -> Observable<Clip> | |
/// Remove clip | |
/// - Parameter at: Target `Clip` to remove | |
func remove(at clip: Clip) -> Observable<Void> | |
/// Bookmark or Unbookmarkd to clip | |
/// - Parameter with: Target `Clip` to bookmark of unbookmark | |
func bookmark(with clip: Clip) -> Observable<Clip> | |
} | |
public struct ClipAPI: ClipAPIType { | |
private let provider: MoyaProvider<ClipTarget> | |
private let userID: Int | |
public init(userID: Int) { | |
provider = MoyaProvider<ClipTarget>() | |
self.userID = userID | |
} | |
public func recentClips(keyword: String = "") -> Observable<[Clip]> { | |
return self.provider.rx | |
.request(.recentClipList(userID: userID, keyword: keyword)) | |
.filterSuccessfulStatusCodes() | |
.map([Clip].self, atKeyPath: "posts") | |
.asObservable() | |
} | |
public func clips(for category: ClipCategory) -> Observable<[Clip]> { | |
return self.provider.rx | |
.request(.categoryClipList(userID: userID, category: category)) | |
.filterSuccessfulStatusCodes() | |
.map([Clip].self, atKeyPath: "posts") | |
.asObservable() | |
} | |
public func add(with clip: Clip) -> Observable<Clip> { | |
return self.provider.rx | |
.request(.addClip(userID: userID, clip: clip)) | |
.filterSuccessfulStatusCodes() | |
.map(Clip.self) | |
.asObservable() | |
} | |
public func remove(at clip: Clip) -> Observable<Void> { | |
return self.provider.rx | |
.request(.removeClip(userID: userID, clip: clip)) | |
.filterSuccessfulStatusCodes() | |
.map { _ in () } | |
.asObservable() | |
} | |
public func bookmark(with clip: Clip) -> Observable<Clip> { | |
return self.provider.rx | |
.request(.bookmark(userID: userID, clip: clip)) | |
.filterSuccessfulStatusCodes() | |
.map(Clip.self) | |
.asObservable() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment