Visitor模式的一些想法

这里有一个例子,不过当时的看法是强调了对象集的操作,现在有了范型,也很少向集合中添加不同类型的对象了。

我认为,这个访问者应该是强调在不改变对象的情况下,添加操作对象的新方法,我模拟了一个动物喂食和游乐的场景,给出对体力值的操作。在无法修改动物类的情况下有些用处,但如果能修改这些类,还是直接添加这些方法好些。
代码是 groovy 的。


// 被访问者接口
interface Animal {
// 输出体力值
void hp();
void accept(Staff staff);
}

// 被访问者
class Cat implements Animal {
int hp = 10;
void hp() {
println(
"I am a cat, my hp is ${hp}.");
}
void accept(Staff staff) {
staff.visit(this);
}
}

class Dog implements Animal {
int hp = 20;
void hp() {
println(
"I am a dog, my hp is ${hp}.");
}
void accept(Staff staff) {
staff.visit(this);
}
}

// 访问者接口,各种人员
interface Staff {
void visit(Animal animal);
}

// 具体访问者(饲养员),使对象增加体力
class Breeder implements Staff {
void visit(Animal animal) {
feed(animal);
}
void feed(Animal animal) {
animal.hp++;
}
}
// 具体访问者(游乐员),使对象减少体力
class Player implements Staff {
void visit(Animal animal) {
play(animal);
}
void play(Animal animal) {
animal.hp--;
}
}


Staff breeder = new Breeder(); Staff player = new Player();
def cat = new Cat(); def dog = new Dog();
cat.accept(breeder); cat.accept(breeder); cat.hp();
dog.accept(player); dog.hp();

很好,结合现在流行的事件驱动,如果在被访问者中安放一个事件触发器,也就是Observable,一旦访问者访问这些被访问者,将触发事件,我们只要在访问者里面监听这些事件,一旦发现,就在访问者中执行相应操作,这是一种现代版本的访问者模式。

我认为函数编程的Lambda表达式其实也是一种访问者模式,如下:
List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
costBeforeTax.stream().map((cost) -> cost + .12*cost)

这是访问集合costBeforeTax中元素,将原来的值进行算术cost + .12*cost运算,这个算法其实是访问行为,是在访问者定义的,而不是定义在被访问者集合的元素中。
[该贴被banq于2014-03-17 18:06修改过]

Java的那个函数表达式写起来还是不够直观,groovy的要好得多。而且如果实现在底层,还是体现不出在业务层的作用,就像iterator模式,现在一个for就能遍历,或者groovy的迭代也很方便,这么多年我就没感觉到在业务层的作用。

访问者模式可以接受访问,这与观察者模式中的被观察者可以接受观察很相似。不同的是观察者模式中的主题是自我改变了状态,然后通知观察者我已经作出了改变,你要相应地去做什么。而访问者模式是要通过访问者来改变被访问者的状态。
[该贴被freebox于2014-03-17 18:53修改过]