generated from pancake-llc/package
-
Notifications
You must be signed in to change notification settings - Fork 16
Visitor Pattern
Aprius edited this page Nov 9, 2024
·
6 revisions
Wikipedia's defintion of the visitor pattern:
A visitor pattern is a software design pattern that separates the algorithm from the object structure. Because of this separation, new operations can be added to existing object structures without modifying the structures. It is one way to follow the open/closed principle in object-oriented programming and software engineering.
In RPG game:
- Healing items can restore health to characters
- Damage effects can deal damage to enemies
Using the Visitor
pattern, we can implement these behaviors without modifying the component classes.
1, Define class visitable, Player
and Enemy
both implement IVisitable
and have methods for taking damage or healing.
using Pancake.Pattern;
using UnityEngine;
public class Player : MonoBehaviour, IVisitable
{
public int hp = 100;
public void Accept(IVisitor visitor) { visitor.Visit(this); }
public void Heal(int amount)
{
hp += amount;
Debug.Log($"Player healed by {amount}. Current Health: {hp}");
}
public void TakeDamage(int amount)
{
hp -= amount;
Debug.Log($"Player took {amount} damage. Current Health: {hp}");
}
}
using Pancake.Pattern;
using UnityEngine;
public class Enemy : MonoBehaviour, IVisitable
{
public int hp = 100;
public void Accept(IVisitor visitor) { visitor.Visit(this); }
public void Heal(int amount)
{
hp += amount;
Debug.Log($"Enemy healed by {amount}. Current Health: {hp}");
}
public void TakeDamage(int amount)
{
hp -= amount;
Debug.Log($"Enemy took {amount} damage. Current Health: {hp}");
}
}
2, Create Specific Visitor Classes for Healing and Damage
-
HealingVisitor
heals thePlayer
by a specified amount. -
DamageVisitor
applies damage to bothPlayer
and Enemy`.
using Pancake.Pattern;
using UnityEngine;
public class HealingVisitor : IVisitor
{
private int _healingAmount;
public HealingVisitor(int healingAmount) { _healingAmount = healingAmount; }
public void Visit<T>(T visitable) where T : Component, IVisitable
{
if (visitable is Player player) player.Heal(_healingAmount);
}
}
using Pancake.Pattern;
using UnityEngine;
public class DamageVisitor : IVisitor
{
private int _damage;
public DamageVisitor(int damage) { _damage = damage; }
public void Visit<T>(T visitable) where T : Component, IVisitable
{
if (visitable is Player player)
{
player.TakeDamage(_damage);
}
else if (visitable is Enemy enemy)
{
enemy.TakeDamage(_damage * 2);
}
}
}
3,
using Pancake.Pattern;
using UnityEngine;
public class Demo : MonoBehaviour
{
public Enemy enemy;
public Player player;
private void Start()
{
IVisitor healingVisitor = new HealingVisitor(20);
IVisitor damageVisitor = new DamageVisitor(15);
player.Accept(healingVisitor); // Heal only the player
enemy.Accept(damageVisitor);
player.Accept(damageVisitor);
}
}