游戏设计模式与实现之:访问者模式 与 信息查询

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);
	}
}

这样去实现一个功能的时候确实是做到了对象与操作的完全解耦合,但是就有一种强行解藕的嫌疑,大致浏览了一下百度上的访问者模式应用与游戏的操作,自己也设想了很多,但是却没有找到一种真正完全切合的应用场景。
而且访问者模式也有一些问题,并没有完全解决原有需求破坏了开闭原则的问题,新加入的子类还是需要去修改每一个实现功能的访问者,当然如果只有新的操作,那是可以不破坏开闭原则的。只能说让读者多熟悉一个设计模式,因为想了很久还是没有想到这个模式有什么广泛的应用场景。因为所有能设想到的场景,都能用更简单一些的方式去完成,也可能是我考虑不周吧,如果有十分切合的场景可以留言告诉博主。

上一篇:访问者模式初理解


下一篇:SQL语言