C# 实现可观察模式
C# Implement Observable Pattern
我正在尝试使用 C# 实现可观察模式。在我的示例代码中,我有两种士兵弓箭手 类:Archer 和 Swordsman 他们实现了 Soldier界面。 Soldier接口有四个方法:
- Attack() - 命令小兵攻击敌人
- Died() - 此方法在该示例中无关紧要
- Kill() - 命令我们的士兵杀死敌人
- BattleCry() - 在 emeny 被杀后庆祝 ALL 我的士兵
和一个 属性 bool IsEnemyKilled
- 当调用 Kill() 方法时 IsEnemyKilled 变为真。
这就是我想要做的:
我知道要实现观察者模式,我需要提供者和观察者。
当其中一名士兵例如弓箭手 - 杀死一个敌人 archer.Kill();
。
IsEnemyKilled
变为真(这是我的提供者)和我所有其他士兵(我的观察者),例如必须通知剑客和另一个弓箭手 IsEnemyKilled
为真,他们必须调用 BattleCry()。
我不知道该怎么做。如果有人提出建议,我将不胜感激。这是我的示例代码。
namespace ImplementObservable
{
class Program
{
static void Main(string[] args)
{
var archer = new Archer();
var swordsman = new Swordsman();
archer.Attack();
archer.Kill();
Console.ReadKey();
}
}
public class Archer : Soldier
{
bool IsEnemyKilled;
// watch somehow prop "IsEnemyKilled" and if it changes to true call BattleCry() for all units
public void Attack()
{
IsEnemyKilled = false;
Console.WriteLine("Archer attack!");
}
public void Died()
{
IsEnemyKilled = false;
Console.WriteLine("Archer died :(");
}
public void Kill()
{
IsEnemyKilled = true;
Console.WriteLine("Archer killed enemy! Hurray!!");
}
public void BattleCry()
{
Console.WriteLine("Archer: Go for victory !");
}
}
public class Swordsman : Soldier
{
bool IsEnemyKilled;
// watch somehow prop "IsEnemyKilled" and if it changes to true call BattleCry() for all units
public void Attack()
{
IsEnemyKilled = false;
Console.WriteLine("Swordsman attack!");
}
public void Died()
{
IsEnemyKilled = false;
Console.WriteLine("Swordsman died :(");
}
public void Kill()
{
IsEnemyKilled = true;
Console.WriteLine("Swordsman killed enemy! Hurray!!");
}
public void BattleCry()
{
Console.WriteLine("Swordsman: Go for victory !");
}
}
public interface Soldier
{
void Kill();
void Attack();
void Died();
void BattleCry();
}
}
您需要将 Subject(某个士兵)附加到观察者(某个其他士兵)。
为此,我首先向 Soldier-Interface 添加了三个新成员:
event Action EnemyKilled;
void Attach(Soldier observer);
void Detach(Soldier observer);
这里的事件是通过属性的setter来通知对象并触发它。我将 属性 更改如下:
private bool isEnemyKilled;
private bool IsEnemyKilled {
get => isEnemyKilled;
set {
isEnemyKilled = value;
if(isEnemyKilled) EnemyKilled?.Invoke();
}
}
Attach
和Detach
的实现如下:
public void Attach(Soldier observer)
{
observer.EnemyKilled += BattleCry;
}
public void Detach(Soldier observer)
{
observer.EnemyKilled -= BattleCry;
}
因为当你必须为两个士兵实施这个时我看到很多重复,考虑将 Soldier
从 interface
更改为 abstract class
。
完成所有这些后,您需要将(所有)士兵连接在一起(当然根据您想要的游戏逻辑)。
跟踪所有士兵的一种方法是 static List<Soldier>
在(您现在的抽象 class)Soldier
中,每个士兵在创建后添加自己。但是你可以在那里做任何你想做的事。
这些只是一些想法,并不是一个成熟的观察者模式。既然你问我想提出一些想法。希望它能让你走上正轨。
另一个提示:如果你只需要 属性 IsEnemyKilled
来通知其他人,你可以简单地忽略它并直接调用事件 EnemyKilled
而不是设置 [=20] =] 到 true
.
我建议将订阅者(观察者)添加到您的提供者(射手)。
这样,您的弓箭手就会有士兵订阅弓箭手的攻击。
Lat 分解一下。
你的射手应该有他的观察员:
public class Archer : Soldier
{
bool IsEnemyKilled;
private List<Soldirer> soldiers = new List<Soldier>();
public void Attack()
...
现在通知胜利:
public void Attack()
{
IsEnemyKilled = false;
Console.WriteLine("Archer attack!");
soldiers.foreach(soldier => soldier.BattleCry());
}
最后,订阅我们的小兵吧:
public class Archer : Soldier {
...
public void subscribe(Soldier) {
soldiers.add(soldier);
}
}
static void Main(string[] args)
{
var archer = new Archer();
var swordsman = new Swordsman();
...
您可以(并且应该)向您的 Soldier class 添加一个警报方法,这样您就可以调用它而不是 BattleCry
方法。
我发现以下文章是一个很好的例子:
https://exceptionnotfound.net/the-daily-design-pattern-observer/
我正在尝试使用 C# 实现可观察模式。在我的示例代码中,我有两种士兵弓箭手 类:Archer 和 Swordsman 他们实现了 Soldier界面。 Soldier接口有四个方法:
- Attack() - 命令小兵攻击敌人
- Died() - 此方法在该示例中无关紧要
- Kill() - 命令我们的士兵杀死敌人
- BattleCry() - 在 emeny 被杀后庆祝 ALL 我的士兵
和一个 属性 bool IsEnemyKilled
- 当调用 Kill() 方法时 IsEnemyKilled 变为真。
这就是我想要做的:
我知道要实现观察者模式,我需要提供者和观察者。
当其中一名士兵例如弓箭手 - 杀死一个敌人 archer.Kill();
。
IsEnemyKilled
变为真(这是我的提供者)和我所有其他士兵(我的观察者),例如必须通知剑客和另一个弓箭手 IsEnemyKilled
为真,他们必须调用 BattleCry()。
我不知道该怎么做。如果有人提出建议,我将不胜感激。这是我的示例代码。
namespace ImplementObservable
{
class Program
{
static void Main(string[] args)
{
var archer = new Archer();
var swordsman = new Swordsman();
archer.Attack();
archer.Kill();
Console.ReadKey();
}
}
public class Archer : Soldier
{
bool IsEnemyKilled;
// watch somehow prop "IsEnemyKilled" and if it changes to true call BattleCry() for all units
public void Attack()
{
IsEnemyKilled = false;
Console.WriteLine("Archer attack!");
}
public void Died()
{
IsEnemyKilled = false;
Console.WriteLine("Archer died :(");
}
public void Kill()
{
IsEnemyKilled = true;
Console.WriteLine("Archer killed enemy! Hurray!!");
}
public void BattleCry()
{
Console.WriteLine("Archer: Go for victory !");
}
}
public class Swordsman : Soldier
{
bool IsEnemyKilled;
// watch somehow prop "IsEnemyKilled" and if it changes to true call BattleCry() for all units
public void Attack()
{
IsEnemyKilled = false;
Console.WriteLine("Swordsman attack!");
}
public void Died()
{
IsEnemyKilled = false;
Console.WriteLine("Swordsman died :(");
}
public void Kill()
{
IsEnemyKilled = true;
Console.WriteLine("Swordsman killed enemy! Hurray!!");
}
public void BattleCry()
{
Console.WriteLine("Swordsman: Go for victory !");
}
}
public interface Soldier
{
void Kill();
void Attack();
void Died();
void BattleCry();
}
}
您需要将 Subject(某个士兵)附加到观察者(某个其他士兵)。
为此,我首先向 Soldier-Interface 添加了三个新成员:
event Action EnemyKilled;
void Attach(Soldier observer);
void Detach(Soldier observer);
这里的事件是通过属性的setter来通知对象并触发它。我将 属性 更改如下:
private bool isEnemyKilled;
private bool IsEnemyKilled {
get => isEnemyKilled;
set {
isEnemyKilled = value;
if(isEnemyKilled) EnemyKilled?.Invoke();
}
}
Attach
和Detach
的实现如下:
public void Attach(Soldier observer)
{
observer.EnemyKilled += BattleCry;
}
public void Detach(Soldier observer)
{
observer.EnemyKilled -= BattleCry;
}
因为当你必须为两个士兵实施这个时我看到很多重复,考虑将 Soldier
从 interface
更改为 abstract class
。
完成所有这些后,您需要将(所有)士兵连接在一起(当然根据您想要的游戏逻辑)。
跟踪所有士兵的一种方法是 static List<Soldier>
在(您现在的抽象 class)Soldier
中,每个士兵在创建后添加自己。但是你可以在那里做任何你想做的事。
这些只是一些想法,并不是一个成熟的观察者模式。既然你问我想提出一些想法。希望它能让你走上正轨。
另一个提示:如果你只需要 属性 IsEnemyKilled
来通知其他人,你可以简单地忽略它并直接调用事件 EnemyKilled
而不是设置 [=20] =] 到 true
.
我建议将订阅者(观察者)添加到您的提供者(射手)。 这样,您的弓箭手就会有士兵订阅弓箭手的攻击。
Lat 分解一下。
你的射手应该有他的观察员:
public class Archer : Soldier
{
bool IsEnemyKilled;
private List<Soldirer> soldiers = new List<Soldier>();
public void Attack()
...
现在通知胜利:
public void Attack()
{
IsEnemyKilled = false;
Console.WriteLine("Archer attack!");
soldiers.foreach(soldier => soldier.BattleCry());
}
最后,订阅我们的小兵吧:
public class Archer : Soldier {
...
public void subscribe(Soldier) {
soldiers.add(soldier);
}
}
static void Main(string[] args)
{
var archer = new Archer();
var swordsman = new Swordsman();
...
您可以(并且应该)向您的 Soldier class 添加一个警报方法,这样您就可以调用它而不是 BattleCry
方法。
我发现以下文章是一个很好的例子: https://exceptionnotfound.net/the-daily-design-pattern-observer/