在我们平时的软件开发中,观察者模式是我们常用的一种模式。在现实生活中,观察者模式也是处处可见。例如:微信中的订阅号,博客的订阅和微博中的关注好友,这些都属于观察者模式的应用。下面是一些我对观察者模式的理解。
一个对象状态改变通知其他对象的问题,而且要考虑到易用和低耦合,保证高度的协作。
下面时该模式的UML类图:
通过上图我们不难发现,观察者模式中的角色如下:
下面我们来实现类图中的代码:
观察者抽象类:
///
/// 抽象观察者类
///
abstract class Observer
{
///
/// 为所有观察者定义接口(更新接口,接到通知时更新自己)
///
public abstract void Update();
}
抽象主题类:
///
/// 抽象主题(抽象通知者)类
///
abstract class Subject
{
private IList observers = new List();
///
/// 增加观察者
///
///
public void Attach(Observer observer)
{
observers.Add(observer);
}
///
/// 移除观察者
///
///
public void Detach(Observer observer)
{
observers.Remove(observer);
}
///
/// 通知所有的观察者
///
public void Notify()
{
foreach (Observer observer in observers)
{
observer.Update();
}
}
}
具体观察者:
///
/// 具体主题(具体通知者)
/// 该类中存在一个状态,改状态变化时通知所有的观察者
///
class ConcreteSubject : Subject
{
private string subjectState;
public string SubjectState
{
get { return subjectState; }
set { subjectState = value; }
}
}
具体观察者类:
///
/// 具体观察者
/// 实现抽象观察者的所有接口,以便于本省状态和通知者状态协调
///
class ConcreteObserver : Observer
{
private string name;
private string observerState;
private ConcreteSubject subject;
public ConcreteSubject Subject
{
get { return subject; }
set { subject = value; }
}
public ConcreteObserver(ConcreteSubject subject,string name)
{
this.subject = subject;
this.name = name;
}
public override void Update()
{
observerState = subject.SubjectState;
Console.WriteLine("观察者{0}的新状态是:{1}", name, observerState);
}
}
测试一下:
//具体通知者
ConcreteSubject s = new ConcreteSubject();
s.Attach(new ConcreteObserver(s, "XX"));
s.Attach(new ConcreteObserver(s, "YY"));
s.Attach(new ConcreteObserver(s, "ZZ"));
s.SubjectState = "ABC";
s.Notify();
测试结果如下:
观察者XX的新状态是:ABC
观察者YY的新状态是:ABC
观察者ZZ的新状态是:ABC
通过对类图的实现我想你已经对观察模式的原理已经理解了,下面我们再来举例说明一下,来加深理解。
我们平时在写一个观察者模式时,可能我们的类中也许并不是这个更新方法满足上面的接口。也就是说抽象通知者依赖抽象观察者这个接口不存在,或者具体观察者没有实现这个更新方法,那么这个通知就无法完成了。此时我们可以使用事件委托实现。下面我们看具体代码:
通知者接口(可能我们这个类只是要具有通知的功能,可能不需要实现这个类,此时用接口比较合适):
///
/// 通知者
///
interface Notify
{
///
/// 通知方法
///
void Notify();
///
/// 属性
///
string SubjectState
{
get;
set;
}
}
这里先声明一个委托:
///
/// 定义一个委托,用来通知更新
///
delegate void EventHandler();
老板类:
class Boss : Notify
{
///
/// 声明一个类型为委托EventHandler的事件,名为Update,
///
public event EventHandler Update;
private string action;
public string SubjectState
{
get { return action; }
set { action = value; }
}
public void Notify()
{
Update();
}
}
看NBA的同事:
///
/// (看NBA的)观察者
///
class ObserverNBA
{
private string name;
private Notify notify;
public ObserverNBA(string name, Notify notify)
{
this.name = name;
this.notify = notify;
}
public void CloseNBAView()
{
Console.WriteLine("{0},{1}关闭NBA直播,继续工作!", notify.SubjectState, name);
}
}
聊天的同事:
///
/// (聊天的)观察者
///
class ObserverChat
{
private string name;
private Notify notify;
public ObserverChat(Notify notify,string name)
{
this.name = name;
this.notify = notify;
}
public void StopChat()
{
Console.WriteLine("{0},{1}停止聊天,开始工作!",notify.SubjectState,name);
}
}
测试一下:
//通知者
Boss huHanSan = new Boss();
//观察者
ObserverNBA tsNBA = new ObserverNBA("张三", huHanSan);
ObserverChat tsChat = new ObserverChat(huHanSan, "李四");
//委托事件(更新方法)
huHanSan.Update += new EventHandler(tsNBA.CloseNBAView);
huHanSan.Update += new EventHandler(tsChat.StopChat);
huHanSan.SubjectState = "我胡汉三又回来了";
//通知者发起通知
huHanSan.Notify();
测试结果:
我胡汉三又回来了,张三关闭NBA直播,继续工作!
我胡汉三又回来了,李四停止聊天,开始工作!
通过以上代码,我想,您已对观察者模式已经有了更深入的理解。下面我们来看看观察者的优缺点。
优点:
缺点:
在下面的情况下可以考虑使用观察者模式:
在unity应用中,使用C#中的事件委托Delegate来彻底解除通知者和观察者之间的耦合。
下面是一个小栗子,仅用来抛砖引玉,不足之处还请见谅。
首先准备UI:
下面是通知者:
using UnityEngine;
using System.Collections;
using System;
using UnityEngine.UI;
///
/// 委托通知的方法类型
///
public delegate void ObserverTest();
///
/// 这个脚本是事件的派发类,
/// 所有发生的事件都由这个类来派发
///
public class Subject : MonoBehaviour
{
public static event ObserverTest ObserverTestEvent;
void Start()
{
Button btn = transform.Find("Button").GetComponent
接着写几个观察者:
观察者1:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
///
/// (按钮)观察者
///
public class ButtonObserver : MonoBehaviour
{
void Start()
{
Subject.ObserverTestEvent += ChangeButton;
}
public void ChangeButton()
{
Button btn = transform.Find("Button (1)").GetComponent
观察者2:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
///
/// (文本)观察者
///
public class TextObserver_1 : MonoBehaviour
{
// Use this for initialization
void Start()
{
Subject.ObserverTestEvent += ChangeText;
}
private void ChangeText()
{
Text txt = transform.Find("Text1").GetComponent();
txt.text = "hi, Eagle1";
}
void OnDestroy()
{
Subject.ObserverTestEvent -= ChangeText;
}
}
观察者3:
using System.Collections;
using UnityEngine.UI;
using UnityEngine;
public class TextObserver_2 : MonoBehaviour
{
// Use this for initialization
void Start()
{
Subject.ObserverTestEvent += ChangeText;
}
private void ChangeText()
{
Text txt = transform.Find("Text2").GetComponent();
txt.text = "hi, Eagle2";
}
void OnDestroy()
{
Subject.ObserverTestEvent -= ChangeText;
}
}
如上图所示把三个观察者都挂在Canvas上,点击左边按钮,效果如下:
到这里,观察者模式的分享就介绍了。观察者模式定义了一种一对多的依赖关系,让多个观察者对象可以同时监听某一个主题对象,这个主题对象在发生状态变化时,会通知所有观察者对象,使它们能够自动更新自己,解决的是“当一个对象的改变需要同时改变多个其他对象”的问题。大家可以以微信订阅号的例子来理解观察者模式。
在文章的最后我们给出上述例子的工程下载链接,方便朋友们探讨交流!本次演示版本Unity5.6.3f1(64-bit),VS2015需要下载的朋友,请点击这里下载。
The End
好了,今天的分享就到这里,如有不足之处,还望大家及时指正,随时欢迎探讨交流!!!
喜欢的朋友们,请帮顶、点赞、评论!您的肯定是我写作的不竭动力!
相关阅读
C# 23种设计模式(unity演示)