具有相关类型和工厂模式的协议?

时间:2018-11-11 13:38:17

标签: swift generics design-patterns swift-protocols

我的数据访问层由通用couchbase.BucketImpl.LookupInBuilder.prototype.executeAsync = () => { return new Promise((resolve, reject) => { this.execute((error, result) => { if (error instanceof Error) { reject(error); } else { resolve(result); } }); }); }; 协议组成

Repository

及其具体实现:

protocol Repository {
    associatedtype T
    func getAll() -> Promise<[T]>
}

基本上,class FirebaseRepository<T: Model>: Repository { func getAll() -> Promise<[T]> { fatalError() } } 可以是RepositoryRestRepositoryFirebaseRepository等。业务逻辑使用存储库:

PlistRepositry

当我尝试将工厂模式应用于存储库时出现问题。这是我首先进入的:

/// My business logic
class ModelService<T: Repository> {
    private let repository: T

    public init(repository: T) {
        self.repository = repository
    }
}

这肯定会导致编译器错误:

/// Returns a concrete Repository implementation
class RepositoryFactory {
    func makeRepository<T: Model>(type: T.Type) -> Repository {
        return FirebaseRepository<T>()
    }
}

我想到的唯一可行的选择是:

Protocol 'Repository' can only be used as a generic constraint because it has Self or associated type requirements

但是,据您了解,强制可选的拆包在生产代码中是不可接受的。

如何使具有关联类型的协议与工厂设计模式一起使用?

1 个答案:

答案 0 :(得分:1)

您可以使用类型擦除。这是一个示例:

protocol CustomProtocol {
    associatedtype AssociatedType
    func foo(argument: AssociatedType)
    func bar() -> AssociatedType
}

如果您想直接使用CustomProtocol,则会收到错误消息:

let array = [CustomProtocol]()
  

协议“ CustomProtocol”只能用作通用约束,因为它具有“自我”或相关类型要求

因此,您可以像Swift一样对它们的序列进行欺骗:

public struct AnyCustomProtocol<T>: CustomProtocol {
    func bar() -> T {
        fatalError("Needs implementation")
    }
    func foo(argument: T) {

    }
}

let array = [AnyCustomProtocol<Any>]() // works fine

在这种情况下,您的问题解决方案将如下所示:

    class Promise<T> {

    }

    protocol Model {

    }

    protocol Repository {
        associatedtype T
        func getAll() -> Promise<[T]>
    }

    class FirebaseRepository<T: Model>: AnyRepository<T> {
        override func getAll() -> Promise<[T]> {
            fatalError()
        }
    }

    class AnyRepository<T>: Repository {
        func getAll() -> Promise<[T]> {
            fatalError()
        }
    }


    class RepositoryFactory {
        func makeRepository<T: Model>(type: T.Type) -> AnyRepository<T> {
            return FirebaseRepository<T>()
        }
    }

__

要进一步阅读,您可以检查thisOfficial docs on Generics