设计模式问题:当扩展和协议失败时

时间:2019-06-15 23:16:42

标签: swift inheritance protocols

使用协议,您可以通过功能存根定义行为;但没有代码。

使用扩展,您可以在项目范围内向要扩展的类的每种类型添加代码和行为;即使其中一些不需要或无法了解此类代码。

Swift中不存在多重继承。

那么,当您拥有所有ViewController的子集时,他们都需要知道如何做相同的事情,并且您不想一次又一次地键入代码或复制/粘贴,该怎么办?但是扩展意味着更多的ViewController获得了它们永远不需要或不知道的代码?

假设我的小应用程序中有10个视图控制器。

其中9个具有多个用于输入数据的UITextField。

在这9个中,有5个具有数据输入要求,这在所有5个中部分相同,但在所有这些中都不通用。例如5个中的3个可能要求输入“年龄”字段,但并非全部5个。其中4个可能需要“ ID号”,而第5个则不需要。

因此,从5个ViewController中,有12个单独的数据输入字段,它们在它们之间共享,但不是在每个字段上共享。

对于所有这12个数据输入字段(UITextFields),都可以编写代码来限制和格式化输入到UITextField中的数据,从而防止出现不正确的数据,例如,年龄超过100,或ID编号>雇员人数等。

问题是这样的:

为UIViewController创建一个扩展可以很容易,该扩展包含所有12个数据输入字段验证代码检查-这确实是我所做的。

但是,由于这些字段仅出现在我的应用程序的10个View Controller中的5个上,因此所有10个View Controller都具有此扩展名。

那么我如何将其限制为仅需要它的5个?

我不需要类中的代码,因为那样的话每个人都必须实例化自己的代码,这是内存中的重复项。

与使用结构相同。

我能想到的唯一解决方案是单例;但我总是回避单例,因为我不确定使用单例是否合理。

2 个答案:

答案 0 :(得分:1)

协议扩展将满足您的需求。 使用您的示例,您可以看到以下内容:

protocol ageValidatable {
    func isValidAge(_ age: Int) -> Bool
}

extension ageValidatable {
    func isValidAge(_ age: Int) -> Bool {
        return age > 0 && age < 150
    }
}

现在,任何实现ageValidatable的ViewController都将默认定义为isValidAge,而无需对其进行定义。你可以

  • 如果愿意,请覆盖
  • 仅将其提供给需要它的ViewControllers
  • 允许ViewController符合这些协议中的多个协议
  • 如果最终符合其中许多协议,则为这些协议的组创建类型别名。即typealias employeeValidatable = ageValidatable & employeeIDValidatable

答案 1 :(得分:0)

从MVC角度严格来说,我可能会给它自己的结构,即InputValidator并将其实例分配给ViewController属性,这样我们就不会在ViewController内部直接拥有业务逻辑。

即使您没有在ViewController中编写这些函数,从技术上讲,它们仍然是其中的一部分,如果您希望将其实现与默认实现不同,则可以将其重写。实例还允许您配置诸如maximumValidAge之类的内容而无需更改代码。