观察者模式
核心描述:“在对象间定义一种 一对多的依赖关系,以便当某个对象的情况发生改变时,与它存在依赖关系的所有对象都能收到通知,并自动进行更新。”
知识点:
1.复习了“继承”和“多态”,包括让子类以接口的身份进行活动。子类可以直接使用父类的方法。
2.将观察者模式分为观察者和被观察者。观察者的身份是一个标签,用接口来实现,继承了这个接口的类都成为了一个观察者。被观察者是一项功能,用被观察者类来实现,继承了这个类的派生类都具备被观察者的能力。
实现流程:
1.创建一个接口IObSevers,用作于观察者身份的标签,创建ModeObSevers和AchievementsObSevers作为两个观察者。
2.创建一个类Subject,用于实现被观察者的功能,包括观察者列表的维护和通知功能。创建一个类PhysicsSubject作为实际的被观察者,继承于Subject。
3.将ModeObSevers和AchievementsObSevers加入到PhysicsSubject的观察者列表中,由PhysicsSubject对前面两个观察者发起通知。
首先要创建一个接口IObSevers:
/// <summary>
/// 所有继承了该接口的子类,都变成了一个观察者,可以直接在被观察者的观察者列表中处理,这个处理的过程是面向对象多态的一种。
/// </summary>
public interface IObSevers {
/// <summary>
/// 被观察者直接调用观察者的该方法,来表示通知的这个过程。
/// </summary>
/// <param name="log"></param>
void OnNotify(string log);
}
上面的接口定义了一个用来“通知”的方法,接下来需要完成一个调用这个通知的类。
实现调用这个“通知”的类:
public class Subject {
/// <summary>
/// 这是一个观察者列表,用来维护被观察者需要通知的观察者对象。
/// </summary>
private List<IObSevers> obSevers = new List<IObSevers>();
/// <summary>
/// 在观察者列表中添加一个观察者。这里对象类型虽然是接口,但实际上是集成了该接口的类以多态的形式出现在这里。
/// </summary>
/// <param name="ob">观察者对象</param>
protected void AddObserver(IObSevers ob)
{
obSevers.Add(ob);
}
/// <summary>
/// 在观察者列表中删除一个观察者。
/// </summary>
/// <param name="ob"></param>
protected void RemoveObsever(IObSevers ob)
{
obSevers.Remove(ob);
}
/// <summary>
/// 通知所有的观察者,参数为事件的类型。
/// </summary>
protected void UpdateNotify()
{
foreach (IObSevers ob in obSevers)
{
if (ob != null)
{
ob.OnNotify("test Log");
}
}
}
}
观察者和被观察者的核心已经实现了,接下来需要让具体的功能模块来完成这样的观察者和被观察者的功能。
首先是在具体的功能模块内实现一个观察者的功能。
创建一个AchievementsObSevers类,成就系统观察者。
public class AchievementsObSevers : IObSevers {
/// <summary>
/// 该观察者收到被观察者的通知后,应该在该方法内对通知的内容进行判断并处理。
/// </summary>
/// <param name="log"></param>
public void OnNotify(string log)
{
//在这里实现被通知后的具体效果。
Debug.Log(log);
}
}
在本文知识点2中提到,所有继承了IObSevers的类都获得了一个观察者的标签。这个成就系统也获得了这个标签。这个成就系统现在就需要等待其他的功能模块发通知,就好像一个观察者开始持续的观察一个被观察者,看这个被观察者是否会出现特定的行为。
下面来实现这个被观察者的功能。
创建一个PhysicsSubject类:
public class PhysicsSubject : Subject {
/// <summary>
/// 创建了一个观察者变量。
/// </summary>
AchievementsObSevers achievements;
/// <summary>
/// 初始化观察者变量,并把它加入到PhysicsSubject的观察者列表中
/// 由于PhysicsSubject继承了Subject,所以子类可以调用父类的方法。
/// </summary>
public PhysicsSubject()
{
achievements = new AchievementsObSevers();
this.AddObserver(achievements);
}
/// <summary>
/// 被观察者通知观察者列表中的所有观察者。注意,这里UpdateNotify()是被this以Subject的身份出现的。
/// </summary>
public void Hello()
{
this.UpdateNotify();
}
}
这个物理模块中,继承了Subject中的所有可以被继承的功能。它自己拥有一个观察者列表,和维护观察者列表的方法。
private List<IObSevers> obSevers = new List<IObSevers>(); protected void AddObserver(IObSevers ob) { } protected void RemoveObserver(IObSevers ob) { }
它将成就系统加入到他的观察者列表后,然后有一个方法Hello()让他向观察者列表中的所有观察者调用了它们的通知。
这样观察者就可以收到这个被观察对象的通知。