GoF解释:
定义一个能够在一个对象结构中,对于所有元素执行的操作。访问者让你可以定义一个新的操作,而不必更改到被操作元素的接口。
模式说明:
当我们需要对一组对象进行统一的操作时,我们定义一个管理类,在开发的过程中,我们因为需求可能不断的增加,那我们的管理类是不是就要不断的增加,这理论上违反了开闭原则。访问者模式通过提供不同的访问者,使用同一个公共接口,访问到不同的数据或者进行不同的操作。
重要的名词:
visitor:访问者,为需要集中处理的对象提供操作方法。
案例分析:为一个基类的所有实现子类提供计数功能
Visitor基类: 预计给英雄和武器提供计数功能
public abstract class IVisitor{
public virtual void VisitHero(IHero hero) {
}
public virtual void VisitWeapon(IWeapon weapon){
}
}
实现计数Visitor
public class CountVisitor : IVisitor{
public int mCount = 0;
public override void VisitHero(IHero hero){
mCount++;
}
public override void VisitWeapon(IWeapon weapon){
mCount++;
}
}
为了更好的说明访问者模式在开放操作上带来的扩展优化,我们可以在实现一个操作,比如现在有个需要,要统计所有英雄和所有武器的战力:
public class GSVisitor : IVisitor {
public int mGS = 0 ;
public override void VisitHero(IHero hero){
mGS += hero.gs;
}
public override void VisitWeapon(IWeapon weapon){
mCount += weapon.gs;
}
}
下面实现IHero 以及 IWeapon,其实就是在传统的基类中,增加一个RunVisitor方法接受IVisitor对象实现操作的扩展
public abstract class IHero{
public int gs ;
public virtual void RunVisitor(IVisitor visitor){
visitor.VisitHero(this);
}
}
public abstract class IWeapon{
public int gs ;
public virtual void RunVisitor(IVisitor visitor){
visitor.VisitHero(this);
}
}
我们为各种基类定义一个同一 的操作入口
public abstract class IContainer{
public abstract void RunVisitor(IVisitor visitor);
}
实现IHero和IWeapon的容器类
public class HeroContainer : IContainer{
public List<IHero> mHeroList = new List<IHero>();
public override void RunVisitor(IVisitor visitor){
foreach(IHero hero in mHeroList)
hero.RunVisitor(visitor);
}
}
public class WeaponContainer : IContainer{
public List<IWeapon> mWeaponList = new List<IWeapon>();
public override void RunVisitor(IVisitor visitor){
foreach(IWeapon weapon in mWeaponList)
weapon.RunVisitor(visitor);
}
}
使用方法,我们这里只测试GSVisitor,
public class TestVisitor{
public void TestGS(){
GSVisitor visitor = new GSVisitor();
HeroContainer heroContainer = new HeroContainer();
heroContainer.RunVisitor(visitor);
Console.WriteLine(visitor.mGS);
}
}
这样去实现一个功能的时候确实是做到了对象与操作的完全解耦合,但是就有一种强行解藕的嫌疑,大致浏览了一下百度上的访问者模式应用与游戏的操作,自己也设想了很多,但是却没有找到一种真正完全切合的应用场景。
而且访问者模式也有一些问题,并没有完全解决原有需求破坏了开闭原则的问题,新加入的子类还是需要去修改每一个实现功能的访问者,当然如果只有新的操作,那是可以不破坏开闭原则的。只能说让读者多熟悉一个设计模式,因为想了很久还是没有想到这个模式有什么广泛的应用场景。因为所有能设想到的场景,都能用更简单一些的方式去完成,也可能是我考虑不周吧,如果有十分切合的场景可以留言告诉博主。