-
Notifications
You must be signed in to change notification settings - Fork 16
Observer Pattern
Wikipedia's defintion of the observer pattern:
The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
So the basic idea is that you should use the observer pattern when you need many objects to receive an update when another object changes. The observer pattern is actually the communication backbone of countless programs and app frameworks, so pay attention.
One example is when you have achievements in your game. This might be difficult to implement if you have several achievements each unlocked by a different behavior. But it's much easier to implement if you know the observer pattern.
1, Create an Observer
for a specific purpose by extending one of the following interfaces
IObserver
IObserver<T>
IObserver<T0, T1>
IObserver<T0, T1, T2>
Implement specific handling logic inside the OnNotify
method
using Pancake.Pattern;
public class KillEnemyObserver : IObserver
{
private readonly int _threshold;
private readonly string _id;
public KillEnemyObserver(string id, int threshold)
{
_id = id;
_threshold = threshold;
}
public void OnNotify()
{
if (UserData.TotalEnemyKilled >= _threshold && !UserData.IsAchievementUnlocked(_id))
{
Debug.LogWarning($"You Killed {_threshold} Enemies");
UserData.UnlockAchievement(_id);
}
}
}
2, Create an Publisher
bằng cách kế thừa từ một trong những class abstract sau:
Publisher
Publisher<T>
Publisher<T0, T1>
Publisher<T0, T1, T2>
These classes all have a protected Notify
method that will iterate over all observers and notice them. You can only call this method from inside a class that inherits from Publisher following the encapsulation principle.
using Pancake.Pattern;
public class KillAchievementPublisher : Publisher
{
public void CheckAndNotify() { Notify(); }
}
3,
using Pancake.Pattern;
public class Demo : MonoBehaviour
{
private readonly KillAchievementPublisher _publisher = new();
private readonly KillEnemyObserver _kill10Enemy = new("kill_10_enemy", 10);
private readonly KillEnemyObserver _kill100Enemy = new("kill_100_enemy", 100);
private readonly KillEnemyObserver _kill1000Enemy = new("kill_1000_enemy", 1000);
private void OnEnable()
{
_publisher.AddObserver(_kill10Enemy);
_publisher.AddObserver(_kill100Enemy);
_publisher.AddObserver(_kill1000Enemy);
}
private void OnDisable()
{
_publisher.RemoveObserver(_kill10Enemy);
_publisher.RemoveObserver(_kill100Enemy);
_publisher.RemoveObserver(_kill1000Enemy);
}
}
Now every time you kill an enemy you can increment your count counter and call your publisher's CheckAndNotify
UserData.TotalEnemyKilled ++;
Debug.LogWarning("TotalEnemyKilled:" + UserData.TotalEnemyKilled);
_publisher.CheckAndNotify();