代码之家  ›  专栏  ›  技术社区  ›  Oni_01

带相关对象的绑定协议.使用Swift的面向协议编程

  •  0
  • Oni_01  · 技术社区  · 6 年前

    我是一个iOS开发人员,有几年使用swift的经验,但很少使用PAT的。。。

    构建器依赖于工厂传递给他的一些变量,但是这些变量是应用程序级别的,所以,要提取这个逻辑并将其放入我的库中,我需要使用一个泛型引用,因为我希望以面向协议的编程方式工作,所以它是一个关联类型。

    // The item that i want to receive from my factory
    protocol Item { 
        var content: String { get }
    }
    
    // This is the Builder interface that the Factory consumes
    protocol Builder {  
    
        // The Abstract Parameters that the Application should define
        associatedtype Parameters
    
        func build(_ parameters: Parameters) -> Item?
    }
    
    // The BusinessResource of my library 
    protocol BusinessResource { }
    
    // The Factory that consumes the Builders
    protocol Factory {
    
        associatedtype FactoryBuilder: Builder
    
        var parameters: FactoryBuilder.Parameters { get }
    
        func make(from businessResource: BusinessResource) -> Item?
    }
    
    // The generic implementation of my Factory
    extension Factory {
    
        func make(from businessResource: BusinessResource) -> Item? {
    
            guard let builder = businessResource as? FactoryBuilder else {
                return nil
            }
            return builder.build(self.parameters)
        }
    }
    

    在这一点上一切看起来都很好。

    我有两个协议,它们绑定在一起,共享一个通用类型(生成器参数)。

    // The concrete parameters of the Application Factory
    struct ConcreteParameters {
        let string: String
    }
    
    // The Builder interface restricting Parameters to ConcreteParameters 
    protocol BindedBuilder: Builder where Parameters == ConcreteParameters {
    
    }
    
    // The Factory interface restricting Parameters to ConcreteParameters 
    protocol BindedFactory: AbstractFactory where FactoryParameters: ConcreteParameters {
    
    }
    

    到目前为止,还不错。一切看起来都就绪,我开始认为这可以工作,所以现在我尝试在应用程序上实现一个具体的工厂,以尝试这是否真的有效。

    // The concrete output of my Builder
    struct ConcreteItem: Item {
        var content: String
    }
    
    // The concrete BusinessResource that i get from my library
    struct ConcreteObject: BusinessResource {
    
        let string: String
    }
    
    // The decoration extension that makes ConcreteObject compliant with Builder
    extension ConcreteObject: Builder {
    
        typealias Parameters = ConcreteParameters
    
        func build(_ parameters: ConcreteParameters) -> Item? {
            return ConcreteItem(content: parameters.string + self.string)
        }
    }
    
    // The real Factory inside my app
    class ConcreteFactory: BindedFactory {
    
        typealias FactoryBuilder = BindedBuilder
    
        var parameters: ConcreteParameters {
            return ConcreteParameters(string: "Hello ")
        }
    }
    
    let item = ConcreteFactory().make(from: ConcreteObject(string: "world!"))
    print(item ?? "NOT WORKING")
    

    在这一点上有些东西断裂了。。。我得到这个错误:

    Error: Type ConcreteFactory does not conform to AbstractFactory

    [ AbstractFactor是当前工厂 ]

    是个虫子?? 我真的不知道怎么解决这个问题。。。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Fran Pugl    6 年前

    我认为在这种情况下,您需要使用一个具体的类型来创建别名 FactoryBuilder 而不是 BindedBuilder ,作为 protocols do not conform to themselves .

    这段代码可以有效地编译,这样的代码是否符合您的要求?

    class ConcreteFactory: BindedFactory {
        typealias FactoryBuilder = ConcreteObject
    
        var parameters: ConcreteParameters {
            return ConcreteParameters(string: "Hello ")
        }
    }
    

    绑定生成器 创造 AnyBindedBuilder