记录整理一下对访问者模式的初步理解。
简介
- 表示一个作用于某对象结构中的各元素的操作。
- 它让我们可以在不改变各元素类的前提下定义作用于这些元素的新操作。
简单的拆分一下:
- 有一个对象结构体,结构体中有很多类,比如结构体中有 Men 和 Woman两种元素类。
- 定义新操作,且不改变元素类。比如 Men 和 Woman 之前有操作:谈恋爱、结婚。后来又有了操作:约会。不需要改动元素类,就可以让客户端实现。将数据操作从对象结构中分享出来。
具体实现看初步使用。
初步使用
需求:
- 有一个对象结构体,里面存放的男人、女人。我们需要展示他们的恋爱、结婚的状态。
- 男人谈恋爱时,输出我有女朋友了。女人谈恋爱时,输出我有男朋友了。
- 男人结婚时,输出我有老婆了。女人结婚时,输出我有老公了。
此处分两步讨论。
- 实现状态:每个男人、女人谈恋爱和结婚时的状态。
- 实现对象结构体:创建一个类,存放男人和女人两种对象,并展示他们的状态。
实现状态:
先实现男人、女人对应的各种状态。
实现1:
- 定义了一个协议 Person,里面有方法 love 和 marry。
- 创建 Man 和 Woman 两个类,遵循协议 Person,各自实现各自的方法。
//男人恋爱时
func love {
print("我有女朋友了")
}
//女人恋爱时
func love {
print("我有男朋友了")
}
//男人结婚时
func marry {
print("我有老婆了")
}
//女人结婚时
func marry {
print("我有老公了")
}
但是,如果又有一个新操作-约会。那么,以上的结构,我们需要
- 在 Person 协议里面再添加一个方法 约会。
- 在 Man 和 Woman 里面添加各自的实现。
这违背了开放封闭的原则,那怎么在新添加操作时,不需要改变已有类呢?
实现2:
- 将操作抽离出来,变成类。
- 有一个 Person 的访问者协议,Visitor,方法是访问所有的 Person。
- 操作类遵循此协议,并实现对应的方法。
- 将 Person 协议里面的方法改成可访问访问者的即可。
- accept:参数是遵循 Visitor 协议的操作对象。
- 各自的实现是,调用 Visitor 里面的 visit 操作。Man 里面调用方法 visitMan,Woman 调用 visitWoman。并将self 传过去。以便访问者 Love 等可以更方便的操作 Person,比如获取 对应 Person 的名字,年龄等属性。
实现对象结构体
代码如下
//对象结构体
struct PersonList {
var pList = [Person]()
func display(vistor: Visitor) {
for person in pList {
person.accept(visitor: vistor)
}
}
}
//外部调用代码
//1、先创建对象结构体里面的元素
let man1 = Man()
let woman1 = Woman()
let man2 = Man()
let woman2 = Woman()
//2、添加到对象结构体中
var pList = PersonList()
pList.pList.append(man1)
pList.pList.append(woman1)
pList.pList.append(man2)
pList.pList.append(woman2)
//3、创建访问者类
let love = Love()
let marry = Marry()
//4、展示对应的状态
pList.display(visitor: love)
pList.display(visitor: marry)
此时,要给对象结构体里面的对象添加约会的操作。
- 创建遵循Visitor 协议的类 Appointment,并实现对应的访问对象的方法。
- 在外部调用的时,新增以下代码
let appointment = Appointment()
pList.display(visitor: appointment)
再次使用
从上面的例子可以对访问者模式有个基础的了解,还有个对员工进行统计的需求也可用到此模式。
- 员工里面有正式员工和临时工
- 人力部门负责统计它们的工时,财务部门负责计算薪资。 参考链接
其它情况,我总结后,再后续补充。
总结
从上面的例子,也可以看到此模式的优点和缺点。比如:如果员工里面又多了一种外派人员、人里面除了男女多了一类。那么程序改起来也很麻烦。