Unity3d之设计模式(三)观察者模式

观察者模式(监听器模式)

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

介绍

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决:使用面向对象技术,可以将这种依赖关系弱化。

关键代码:在抽象类里有一个 ArrayList 存放观察者们。


优点:

1、观察者和被观察者是抽象耦合的。双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。

2、建立一套触发机制。

缺点: 

1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 

3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。


类图:


应用实例:

using UnityEngine;
using System.Collections.Generic;

public class TestObserver : MonoBehaviour {

	// Use this for initialization
	void Start () {
        // 具体主题角色通常用具体自来来实现
        ConcreteSubject subject = new ConcreteSubject();

        subject.Attach(new ConcreteObserver(subject, "Observer A"));
        subject.Attach(new ConcreteObserver(subject, "Observer B"));
        subject.Attach(new ConcreteObserver(subject, "Observer C"));

        subject.SubjectState = "Ready";
        subject.Notify();

    }
}

/// <summary>
/// 抽象主题类
/// </summary>
public abstract class Subject
{
    private List<Observer> observers = new List<Observer>();

    /// <summary>
    /// 增加观察者
    /// </summary>
    /// <param name="observer"></param>
    public void Attach(Observer observer)
    {
        observers.Add(observer);
    }

    /// <summary>
    /// 移除观察者
    /// </summary>
    /// <param name="observer"></param>
    public void Detach(Observer observer)
    {
        observers.Remove(observer);
    }

    /// <summary>
    /// 向观察者(们)发出通知
    /// </summary>
    public void Notify()
    {
        foreach (Observer o in observers)
        {
            o.Receive();
        }
    }
}

/// <summary>
/// 抽象观察者类,为所有具体观察者定义一个接口,在得到通知时更新自己
/// </summary>
public abstract class Observer
{
    public abstract void Receive();
}

/// <summary>
/// 具体观察者或具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
/// </summary>
public class ConcreteSubject : Subject
{
    private string subjectState;

    /// <summary>
    /// 具体观察者的状态
    /// </summary>
    public string SubjectState
    {
        get { return subjectState; }
        set { subjectState = value; }
    }
}

/// <summary>
/// 具体观察者,实现抽象观察者角色所要求的更新接口,已是本身状态与主题状态相协调
/// </summary>
public class ConcreteObserver : Observer
{
    private string observerState;
    private string name;
    private ConcreteSubject subject;

    /// <summary>
    /// 具体观察者用一个具体主题来实现
    /// </summary>
    public ConcreteSubject Subject
    {
        get { return subject; }
        set { subject = value; }
    }

    public ConcreteObserver(ConcreteSubject subject, string name)
    {
        this.subject = subject;
        this.name = name;
    }

    /// <summary>
    /// 实现抽象观察者中的更新操作
    /// </summary>
    public override void Receive()
    {
        observerState = subject.SubjectState;
        Debug.LogFormat("The observer's state of {0} is {1}", name, observerState);
    }
}


unity应用中:使用C#中的事件委托Delegate来彻底解除通知者和观察者之间的耦合。

关于委托:委托是一种函数指针。一旦为委托分配了方法,委托将与该方法有相同的行为。委托方法可以像其它任何方法一样,具有参数和返回值。委托可以看作是对函数(方法)的的抽象,是特殊的函数类”,委托的实例代表一个(或多个)具体的函数,它可以是多路广播的。

 

下面例子分别用观察者模式,委托机制来实现

类图实例描述:客户支付了订单款项,这时财务需要开具发票,出纳需要记账,配送员需要配货。

观察者模式的实现

类图:

    

代码实现

using UnityEngine;
using System.Collections.Generic;

public class TestSubject : MonoBehaviour {

    Customer subject;
    // Use this for initialization
    void Start () {
        subject = new Customer();

        subject.Attach(new Accountant(subject));
        subject.Attach(new Cashier(subject));
        subject.Attach(new Dilliveryman(subject));
    }
	
	// Update is called once per frame
	void Update () {
        subject.Notify();
    }
}


/// <summary>
/// 抽象被观察者
/// </summary>
public interface ISubject
{
    void Notify();
}

/// <summary>
/// 工作岗位,抽象观察者
/// </summary>
public abstract class JobStation
{
    public abstract void Received();
}

/// <summary>
/// 具体客户
/// </summary>
public class Customer : ISubject
{
    private List<JobStation> observers = new List<JobStation>();

    /// <summary>
    /// 增加观察者
    /// </summary>
    /// <param name="observer"></param>
    public void Attach(JobStation observer)
    {
        this.observers.Add(observer);
    }

    /// <summary>
    /// 移除观察者
    /// </summary>
    /// <param name="observer"></param>
    public void Detach(JobStation observer)
    {
        this.observers.Remove(observer);
    }

    public void Notify()
    {
        foreach (JobStation o in observers)
        {
            o.Received();
        }
    }
}

/// <summary>
/// 会计
/// </summary>
public class Accountant : JobStation
{
    private Customer customer;
    public Accountant(Customer customer)
    {
        this.customer = customer;
    }

    /// <summary>
    /// 更新状态
    /// </summary>
    public override void Received()
    {
        Debug.Log("我是会计,我来开具发票。");
    }
}

/// <summary>
/// 出纳
/// </summary>
public class Cashier : JobStation
{
    private Customer customer;
    public Cashier(Customer customer)
    {
        this.customer = customer;
    }

    public override void Received()
    {
        Debug.Log("我是出纳员,我给登记入账。");
    }
}

/// <summary>
/// 快递员
/// </summary>
public class Dilliveryman : JobStation
{
    private Customer customer;
    public Dilliveryman(Customer customer)
    {
        this.customer = customer;
    }

    public override void Received()
    {
        Debug.Log("我是配送员,我来发货。");
    }
}


C#委托实现观察者模式:

类图:

    

通过类图来看,观察者和主题之间已经不存在任何依赖关系了。

using UnityEngine;

/// 具体被观察者
public class Customer : MonoBehaviour
{
    /// 声明委托
    public delegate void CustomerEventHandler();

    // 创建委托
    public static CustomerEventHandler Handler;

    //有购买行为,就发送事件
    void Update()
    {
        Handler();
    }
}

/// <summary>
/// 财务,已经不需要实现抽象的观察者类,并且不用引用具体的主题
/// </summary>
public class Accountant : MonoBehaviour
{
    void Start()
    {
        // 注册事件
        Customer.Handler += GiveInvoice;
    }
    /// <summary>
    /// 开发票
    /// </summary>
    public void GiveInvoice()
    {
        Debug.Log("我是会计,我来开具发票。");
    }
}

/// <summary>
/// 出纳,已经不需要实现抽象的观察者类,并且不用引用具体的主题
/// </summary>
public class Cashier : MonoBehaviour
{
    void Start()
    {
        // 注册事件
        Customer.Handler += Recoded;
    }
    public void Recoded()
    {
        Debug.Log("我是出纳员,我给登记入账。");
    }
}

/// <summary>
/// 配送员,已经不需要实现抽象的观察者类,并且不用引用具体的主题
/// </summary>
public class Dilliveryman : MonoBehaviour
{
    void Start()
    {
        // 注册事件
        Customer.Handler += Dilliver;
    }

    public void Dilliver()
    {
        Debug.Log("我是配送员,我来发货。");
    }
}



参考:http://www.cnblogs.com/wangjq/archive/2012/07/12/2587966.html

参考:http://www.runoob.com/design-pattern/design-pattern-tutorial.html

  • 12
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Unity中的观察者模式是一种设计模式,用于实现对象之间的一对多依赖关系。它允许一个被观察的对象(称为主题或被观察者)维护一组依赖于它的对象列表(称为观察者),并在状态发生变化时自动通知观察者。 在Unity中,可以使用C#语言和相关的Unity API来实现观察者模式。下面是一个简单的示例: ```csharp // 定义观察者接口 public interface IObserver { void OnNotify(); } // 定义被观察者类 public class Subject { private List<IObserver> observers = new List<IObserver>(); public void AddObserver(IObserver observer) { observers.Add(observer); } public void RemoveObserver(IObserver observer) { observers.Remove(observer); } public void NotifyObservers() { foreach (var observer in observers) { observer.OnNotify(); } } } // 实现观察者类 public class Observer : IObserver { public void OnNotify() { // 处理通知的逻辑 } } // 使用观察者模式 public class Example : MonoBehaviour { private Subject subject = new Subject(); private Observer observer = new Observer(); private void Start() { subject.AddObserver(observer); } private void Update() { if (Input.GetKeyDown(KeyCode.Space)) { subject.NotifyObservers(); } } } ``` 在上面的示例中,Subject类是被观察者,它维护了一个观察者列表。Observer类是观察者,它实现了IObserver接口的OnNotify方法来处理通知的逻辑。Example类演示了如何使用观察者模式,在Start方法中将观察者添加到被观察者的列表中,在Update方法中按下空格键时通知观察者。 这只是一个简单的例子,实际应用中可能会有更复杂的场景和逻辑。观察者模式Unity中的应用广泛,可以用于处理事件、消息传递、UI更新等各种情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TxNet.Ltd.

你的赞同是对我的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值