The Visitor Design Pattern can be used when you need to perform an action on the object but the logic isn't semantically correct to be placed in that object. So we can have an external object “visit” that instance and call an action to be performed.
In games we could use this pattern on attacks. In the game Breath of Fire IV, for example, there are many types of attacks and various types of creatures. One might recover life instead of taking damage depending on the type of attack. The logic to determine what happens after an attack happens can be isolated on a visitor.
To do that we will need the visitor. The visitor declares a method that requires an object that it will visit. In this example I made one visitor that can access Units.
- public interface IVisitor<T> where T: Unit
- {
- void Visit(T unit);
- }
-
- public class GigaFlare : IVisitor<Unit>
- {
- public int Damage { get; private set; }
-
- public GigaFlare()
- {
- Damage = 100;
- }
-
-
-
- public void Visit(Unit unit)
- {
- if (unit.AbsorbsFire)
- {
- unit.HealthPoints += Damage;
- }
- else
- {
- unit.HealthPoints -= Damage - unit.DefensePoints;
- }
- }
- }
And we also need the Unit. The Unit has a method that accepts the visitor and allows the visitor to visit the instance accepting it.
- public abstract class Unit
- {
- public int HealthPoints { get; set; }
-
- public int DefensePoints { get; set; }
-
- public bool AbsorbsFire { get; set; }
-
-
-
- public void Accept(IVisitor<Unit> visitor)
- {
- visitor.Visit(this);
- }
- }
-
- public class Goo : Unit
- {
- public Goo()
- {
- HealthPoints = 100;
- DefensePoints = 50;
- }
- }
-
- public class FireGoo : Goo
- {
- public FireGoo()
- {
- AbsorbsFire = true;
- }
- }
In short this is what is happening:
- visits accepts changes
- ------> Unit ------> GigaFlare -------> Unit
If we now put it to a test:
- var goo = new Goo();
- var fgoo = new FireGoo();
-
- var gigaFlare = new GigaFlare();
-
- goo.Accept(gigaFlare);
- fgoo.Accept(gigaFlare);
The result will be:
In another example, similar to this one, is on Starcraft where a siege tank does various amounts of damage to various units. The projectile visit units and handles damage appropriately. A Pattern Craft video from John Lindquist shows it: PatternCraft - Visitor Pattern.