加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

如何在Swift中使用访问者模式减少样板?

发布时间:2020-12-14 04:59:57 所属栏目:百科 来源:网络整理
导读:我正在 Swift 2.2中为工作项目实现访问者模式. 因此,我不必简化我的源代码,并节省一些时间,我将使用example of visitor pattern in swift by Oktawian Chojnacki. protocol PlanetVisitor { func visit(planet: PlanetAlderaan) func visit(planet: PlanetCo
我正在 Swift 2.2中为工作项目实现访问者模式.

因此,我不必简化我的源代码,并节省一些时间,我将使用example of visitor pattern in swift by Oktawian Chojnacki.

protocol PlanetVisitor {
    func visit(planet: PlanetAlderaan)
    func visit(planet: PlanetCoruscant)
    func visit(planet: PlanetTatooine)
}

protocol Planet {
    func accept(visitor: PlanetVisitor)
}

class PlanetAlderaan: Planet {
    func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}
class PlanetCoruscant: Planet {
    func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}
class PlanetTatooine: Planet {
    func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}

class NameVisitor: PlanetVisitor {
    var name = ""

    func visit(planet: PlanetAlderaan)  { name = "Alderaan" }
    func visit(planet: PlanetCoruscant) { name = "Coruscant" }
    func visit(planet: PlanetTatooine)  { name = "Tatooine" }
}

我一直试图解决的问题是减少派生自Planet的每个类的样板.
正如你所看到的,他们都有相同的功能重复func接受(访问者:PlanetVisitor){visitor.visit(self)}.

我已经尝试在Planet协议上放置一个默认实现并在基类上实现它,并且由于编译时重载解析,Swift似乎不允许它.

例子:

协议的默认实施:

extension Planet {
    func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}

基类:

class PlanetBase: Planet {
    func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}

class PlanetAlderaan: PlanetBase {}
class PlanetCoruscant: PlanetBase {}
class PlanetTatooine: PlanetBase {}

有没有人知道一种方法,接受函数可以通用并自动应用于派生自Planet的每个具体类?这不是一个关键问题,但它是一个很棒的难题!

解决方法

简短的回答:不可能,这是设计的.

当您拥有稳定数量的行星但未知数量的访客时,访客模式适用于该情况.因此,您计划访问者的未来扩展,编写此样板文件一次.无需更改行星即可添加更多访客.

在大型项目中,您可以使用代码生成.

不推荐,你的替代方案是直接切换行星,不需要样板代码:

func foo(planet: Planet) {
    if planet is PlanetAlderaan {
        name = "Alderaan"
    }
    else if planet is PlanetCoruscant {
        name = "Coruscant"
    }
    else if planet is PlanetTatooine {
        name = "Tatooine"
    }
}

这很容易出错,因为你很容易忘记行星.访问者模式强制您为所有情况编写代码,否则将无法编译.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读