码迷,mamicode.com
首页 > 其他好文 > 详细

游戏前端开发的必要设计--观察者模式的应用

时间:2015-06-23 17:31:37      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:

游戏开发设计,尤其是在前端开发中观察者模式是一个非常有用的设计。在这里我所讲的观察者模式不同于教科书上。

这里我把观察者和发布者结合,两者并存于一体。这样的一个设计使得他可以完整的模拟现实中的对象和对象之间的所有交互。

下面是C#语言版本的实现。

 Actor.cs 这个类用于提供发送和接受

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
/// <summary>
/// 信号接收者处理各自逻辑的回调
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="signal"></param>
public delegate void OnSignalHandler<T>(Signal<T> signal);
/// <summary>
/// 用于实现观察者和主题发布者
/// instance.Add()添加感兴趣的主题并对应处理
/// instance.Send()发送主题
/// 解耦发送者和接受者之间的强引用关系
/// 达到数据通信之间的弱关系
/// 达到高维护性的目的
/// </summary>
public class Actor
{
    /// <summary>
    /// 信号字典
    /// </summary>
    private Dictionary<Enum, Delegate> signalDict = new Dictionary<Enum, Delegate>(); 
    /// <summary>
    /// 管理器
    /// </summary>
    private ActorManager actorManager = ActorManager.GetInstance();
    /// <summary>
    /// 发送者
    /// </summary>
    private object target = null;
    /// <summary>
    /// 生命状态控制
    /// </summary>
    private byte lifeCondition = 1;//1:awake 0;sleep
    /// <summary>
    /// 缺省状态下 target==null
    /// </summary>
    public Actor()
    {

    }
    /// <summary>
    /// 可选 target 用于需要
    /// </summary>
    /// <param name="target"></param>
    public Actor(object target)
    {
        this.target = target;
    }
    /// <summary>
    /// 不可手动调用
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="type"></param>
    /// <param name="signal"></param>
    public void handler<T>(Enum type, Signal<T> signal)
    {
        if (lifeCondition == 0) return;
        if (signalDict.ContainsKey(type))
        {
            OnSignalHandler<T> caller = signalDict[type] as OnSignalHandler<T>;
            if (caller != null)
            {
                caller(signal);
            }
        }
    }
    /// <summary>
    /// 添加关注
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="type"></param>
    /// <param name="caller"></param>
    public void Add<T>(Enum type, OnSignalHandler<T> caller)
    {
        this.signalDict.Add(type, caller);
        this.actorManager.Add(type, this);
    }
    /// <summary>
    /// 移除关注
    /// </summary>
    /// <param name="type"></param>
    public void Remove(Enum type)
    {
        this.signalDict.Remove(type);
        this.actorManager.Remove(type, this);
    }

    /// <summary>
    /// 移除全部
    /// </summary>
    public void RemoveAll()
    {        
        Dictionary<Enum, Delegate>.KeyCollection keys = this.signalDict.Keys;
        Enum[] tempArr = new Enum[keys.Count];
        keys.CopyTo(tempArr, 0);
        foreach (Enum key in tempArr)
        {
            Remove(key);
        }            
    }
    /// <summary>
    /// 发送信号
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="type"></param>
    /// <param name="obj"></param>
    public void Send<T>(Enum type, T obj)
    {
        Signal<T> data = new Signal<T>(obj);     
        data.type = type;
        data.target = target == null ? this : target;
        actorManager.Send<T>(type, data);
    }
    /// <summary>
    /// 唤醒状态
    /// </summary>
    public void Awake()
    {
        lifeCondition = 1;
    }
    /// <summary>
    /// 休眠状态
    /// </summary>
    public void Sleep()
    {
        lifeCondition = 0;
    }
    public void Destory()
    {
        this.RemoveAll();
        this.actorManager = null;
        this.signalDict = null;
        this.target = null;
    }
}
View Code

 ActorManager.cs 这个类管理所有的Actor

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Collections;


public class ActorManager
{
    private Dictionary<Enum, List<Actor>> signalDict;
    private static ActorManager ins;
    private ActorManager()
    {        
        signalDict = new Dictionary<Enum, List<Actor>>();
    }
    /// <summary>
    /// 添加actor的信号类型
    /// </summary>
    /// <param name="type"></param>
    /// <param name="observer"></param>
    public void Add(Enum type, Actor observer)
    {
        List<Actor> obsers;
        if (this.signalDict.ContainsKey(type))
        {
            obsers = this.signalDict[type] as List<Actor>;
            if (!obsers.Contains(observer))
                obsers.Add(observer);
        }
        else
        {
            obsers = new List<Actor>();
            this.signalDict.Add(type, obsers);
            obsers.Add(observer);
        }
    }
    /// <summary>
    /// 移除指定的actor的信号类型
    /// </summary>
    /// <param name="type"></param>
    /// <param name="observer"></param>
    public void Remove(Enum type, Actor observer)
    {
        List<Actor> obsers;
        if (this.signalDict.ContainsKey(type))
        {
            obsers = this.signalDict[type] as List<Actor>;
            if(obsers.Contains(observer))
                obsers.Remove(observer);
        }
    }
    /// <summary>
    /// 单例 获得
    /// </summary>
    /// <returns></returns>
    public static ActorManager GetInstance()
    {
        if (null == ins)
            ins = new ActorManager();
        return ins;
    }
    /// <summary>
    /// 发送信号数据
    /// </summary>
    /// <param name="type"></param>
    /// <param name="data"></param>
    public void Send<T>(Enum type, Signal<T> data)
    {
        if (this.signalDict.ContainsKey(type))
        {
            List<Actor> obsers = this.signalDict[type] as List<Actor>;
            int count = obsers.Count;
            for (int i = 0; i < count; ++i)
            {
                obsers[i].handler<T>(type, data);
            }           
        }
    }


        
}
View Code

 

·上面的代码介绍完了。那么我们能用它来实现什么样的功能需求呢?

试想一下这么一个情景:在一个教室里有这么几个人,一个会汉语和英语的中国人,一个只会日语的日本人,一个只会讲英语的英国人,还有一个他们三种语言的

语言学教授。他们在一起交流的过程中有一部分人能听懂而有一部分人听不懂。中国人说英语的时候会只有日本人不会有所反应,而日本人说日语的时候中国人和

英国人是听不懂的。

 

下面我们首先构造一个人的基类 。实现一些简单的功能

Human.cs 这个类

技术分享
using System;
using System.Collections.Generic;


public class Human
{
    public enum Language
    {
        Chinese,
        English,
        Japanese,
    }
    protected string name;
    protected Actor actor = new Actor();
    public Human(string name)
    {
        this.name = name;
    }
    public virtual void Talk(Enum language, string value)
    {
        System.Console.WriteLine(name + "\t 说 \t" + value);
        actor.Send<string>(language, value);
    }
    
}
View Code
技术分享
using System;
using System.Collections.Generic;

/// <summary>
/// 中国人
/// </summary>
public class Chinese:Human
{
    public Chinese(string name)
        : base(name)
    {
        //会中文
        actor.Add<string>(Language.Chinese, hearChineseHandler);
        //会英语
        actor.Add<string>(Language.English, heareEnglishHandler);
    }

    private void hearChineseHandler(Signal<string> signal)
    {
        System.Console.WriteLine(name + "\t 听到了\t " + signal.data);
    }

    private void heareEnglishHandler(Signal<string> signal)
    {
        System.Console.WriteLine(name + "\t 听到了\t " + signal.data);
    }
}
View Code

 

技术分享
using System.Collections;
/// <summary>
/// 英国人
/// </summary>
public class English : Human
{
    public English(string name)
        : base(name)
    {
        //只会英语
        actor.Add<string>(Language.English,hearEnglistHandler);
    }


    private void hearEnglistHandler(Signal<string> signal)
    {
        System.Console.WriteLine(name + "\t 听到了\t " + signal.data);
    }
}
View Code
技术分享
using System.Collections;
/// <summary>
/// 日本人
/// </summary>
public class Japanese : Human
{
    public Japanese(string name)
        : base(name)
    {
        //只会日语
        actor.Add<string>(Language.Japanese, hearJapaneseHandler);
    }


    private void hearJapaneseHandler(Signal<string> signal)
    {
        System.Console.WriteLine(name + "\t 听到了\t " + signal.data);
    }
}
View Code
技术分享
using System.Collections;
/// <summary>
/// 语言学家
/// </summary>
public class Philologer : Human
{
    public Philologer(string name)
        : base(name)
    {
        //会中文
        actor.Add<string>(Language.Chinese, hearChineseHandler);
        //会英语
        actor.Add<string>(Language.English, heareEnglishHandler);
        //会日语
        actor.Add<string>(Language.Japanese, hearJapaneseHandler);
    }


    private void hearJapaneseHandler(Signal<string> signal)
    {
        System.Console.WriteLine(name + "\t 听到了\t " + signal.data);
    }

    private void hearChineseHandler(Signal<string> signal)
    {
        System.Console.WriteLine(name + "\t 听到了\t " + signal.data);
    }

    private void heareEnglishHandler(Signal<string> signal)
    {
        System.Console.WriteLine(name + "\t 听到了\t " + signal.data);
    }
}
View Code
技术分享
class Program
    {        
        static void Main(string[] args)
        {
           
            Chinese chi = new Chinese("小张");
            English eng = new English("查理");
            Japanese jap = new Japanese("坂本龙马");
            Philologer phi = new Philologer("语言学叫兽");

            //test
            chi.Talk(Human.Language.Chinese, "你好");//小张 和 叫兽 能听到
            System.Console.WriteLine("--------------------------------");
            jap.Talk(Human.Language.Japanese, "斯国一");//坂本龙马 和 叫兽 能听到
            System.Console.WriteLine("--------------------------------");
            eng.Talk(Human.Language.English, "hello");//小张 查理 和 叫兽 能听到
            System.Console.WriteLine("--------------------------------");
            phi.Talk(Human.Language.English, "i am a professor");//小张 查理 和 叫兽 能听到
            System.Console.ReadKey();
        }
    }
View Code

 技术分享

游戏前端开发的必要设计--观察者模式的应用

标签:

原文地址:http://www.cnblogs.com/monkeycoder/p/4588412.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!