设计模式——访问者模式
2020-10-31 本文已影响0人
DevilRoshan
什么是访问者模式?
封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
实现
// 人的抽象类。只有一个“接受”的抽象方法,它是用来获得“状态”对象的。
type Person interface {
Accept(action Action)
}
type Man struct {
}
func NewMan() *Man {
return &Man{}
}
func (this *Man) Accept(action Action) {
action.GetManAction(*this)
}
type Woman struct {
}
func NewWoman() *Woman {
return &Woman{}
}
func (this *Woman) Accept(action Action) {
action.GetWomanAction(*this)
}
// 反应,男人反应,女人反应
type Action interface {
GetManAction(man Man)
GetWomanAction(woman Woman)
}
// Action 的具体上实现,成功,失败
type Success struct {
}
func NewSuccess() *Success {
return &Success{}
}
func (this *Success) GetManAction(man Man) {
fmt.Println("男人成功...")
}
func (this *Success) GetWomanAction(woman Woman) {
fmt.Println("女人成功...")
}
type Failure struct {
}
func NewFailure() *Failure {
return &Failure{}
}
func (this *Failure) GetManAction(man Man) {
fmt.Println("男人失败...")
}
func (this *Failure) GetWomanAction(woman Woman) {
fmt.Println("女人失败...")
}
// 结构对象
type ObjectStructure struct {
elements []Person
}
func NewObjectStructure() *ObjectStructure {
return &ObjectStructure{}
}
func (this *ObjectStructure) Attach(person Person) {
this.elements = append(this.elements, person)
}
func (this *ObjectStructure) Detach(person Person) {
for idx, value := range this.elements {
if value == person {
this.elements = append(this.elements[:idx], this.elements[idx+1])
}
}
}
func (this *ObjectStructure) Display(action Action) {
for _, person := range this.elements {
person.Accept(action)
}
}
func TestNewObjectStructure(t *testing.T) {
objectStructure := NewObjectStructure()
objectStructure.Attach(NewMan())
objectStructure.Attach(NewWoman())
// 成功
success := NewSuccess()
objectStructure.Display(success)
// 失败
failure := NewFailure()
objectStructure.Display(failure)
}
// === RUN TestNewObjectStructure
// 男人成功...
// 女人成功...
// 男人失败...
// 女人失败...
// --- PASS: TestNewObjectStructure (0.00s)
// PASS
优点
- 符合单一职责原则;
- 优秀的扩展性;
- 灵活性非常高。
缺点
- 具体元素对访问者公布细节,也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的;
- 具体元素变更比较困难;
- 违背了依赖倒转原则。访问者依赖的是具体元素,而不是抽象元素。
使用场景
- 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖与其具体类的操作,也就是用迭代器模式已经不能胜任的情景;
- 需要对一个对结构中的对象进行很多不同并且不相关的操作,而你想避免让这些操作“污染”这些对象。