Skip to content

Instantly share code, notes, and snippets.

@ppth0608
Created July 7, 2019 09:58
Show Gist options
  • Save ppth0608/03bba7ee850d8362458012af8c62d042 to your computer and use it in GitHub Desktop.
Save ppth0608/03bba7ee850d8362458012af8c62d042 to your computer and use it in GitHub Desktop.
How to implement `DI(Dependency Injection)` with `Service` pattern
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