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

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

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

下面是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;
    }
}

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);
            }
        }
    }

}

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

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

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

英国人是听不懂的。

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

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);
    }

}

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);
    }
}

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);
    }
}

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);
    }
}

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);
    }
}

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();
        }
    }

时间: 2024-08-03 13:18:30

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

[转载]HTML5游戏前端开发秘籍

http://isux.tencent.com/html5-game-development-cheats.html 转载至腾讯ISUX HTML5游戏前端开发秘籍 本文由米随随编写 QQ空间Android版4.2和4.5上线的玩吧游戏“空间疯狂套牛”是一款使用HTML5开发出的手机游戏,虽然还有很多不足,但其中使用的一些技术与技巧还是很有必要为大家分享出来,方便大家用秘籍打通各种关卡创造出更多更好的HTML5游戏.(本秘籍主要讲述使用HTML + CSS技术方面) 一.自适应 Android手

web前端开发与页面设计的协作、区别与发展

web前端开发与页面设计的协作.区别与发展,布布扣,bubuko.com

常用网站--前端开发类+网页设计类+平面素材类+flash类

前端开发类 animate CSS 前端开发网 我爱CSS 大家网 W3School jQuery开发技术详解教程视频 jQuery中文社区 jQueryChina 网页设计类 禅意花园 CSS Downunder CSS Impress CSS New websitelaunchpad wpglobe UI Maker 平面素材类 站酷网 昵图网 书法字体 图萝网 素彩网 三联素材 flash类 牛图库 Pian Tou 68 flash flash 片头之家 jQuery JavaScrip

游戏前端开发随笔【2】

1, 游戏开发经常遇到需要和后端调试的时候,也就是协议有问题的时候, 应该后端在协议发送处断点, 前端在编解码断点, 确保不是因为前端修改过的数据. 2, 尽量复用组件. 当游戏开发一段时间后,会有各种各样的组件.比如说倒计时. 作为后来者,用一个组件的代价是挺大的,因为要学习,因为会耦合. 不过为了方便同事检阅,还是尽量用公用的组件,尽量避免自己造轮子,即使自己的轮子更容易用. 3, public 的函数,尽量判断null,保证不报错. 自己写的函数大致分为,public/private/pr

谈谈XAML前端开发

GUI的发展 在图形用户界面的操作系统(Windows,MAC)出现之前,计算机软件是命令行界面的程序,用户和程序的交互是通过输入命令,查看命令运行结果进行的.当然很不友好.后来出现了文本图形界面的程序,即用制表符等特殊文本拼接出图形界面的效果,来使程序以图形界面的方式和用户交互.出现了菜单项,状态栏等概念,当时在DOS下流行的QBASIC,TurboC等IDE就是典型的文本图形界面程序. 随着Windows操作系统的普及,GUI(图形界面)程序的交互方式成为了用户和计算机交互的标准方式.Win

[转]关于Web前端开发,附:(百度web前端笔试面试题目)

关于Web前端及百度web前端笔试面试题目 随着各大互联网公司设立了Web前端开发工程师.设计工程师等职位,web前端越来越得到互联网企业的认可.而且其重视程度与地位也随着浏览器 端的富客户端的体现而日益提高. 眼前对HTML5的未来和走向,业内的预测是会和Flash.Silverlight等相结合,从而取代传统的客户端应用程序.而实现这个目标的客户端核 心工作是有Web前端工程师来完成的. 从另一个角度,对于web产品来说,交互和用户体验是产品的第一价值,这部分价值的体现就是在web前端.可以

某互联网(特大型)公司游戏元数据管理系统前端开发技术

本人于去年十月份开始接收游戏元数据管理系统的开发,下面就把使用的技术总结一下: 由于元数据数据库比较多,链接频繁会影响效率,所以我们使用了facebook开源的Thrift,服务端使用C++,客户端链接使用python和php,由于我主要做php,下面是Thrift的php客户端入口文件: <?php #Thrift Lib Path Root $GLOBALS['THRIFT_ROOT']=$_SERVER['DOCUMENT_ROOT']."/application/Thrift/li

大前端应用开发与架构设计-使用HTML构建Web站点

大前端应用开发与架构设计-使用HTML构建Web站点 大前端应用开发与架构设计 2.1 Web基础介绍 2.1.1 了解互联网应用程序的架构 什么叫做互联网? 互联网:通过网络(有线.无线,4G)将世界各地的计算机(手机.平板.PC.服务器)连接起来的结构. 随着互联网及其相关技术的不断发展,目前基于互联网的程序有B/S(Broswer/Server)架构和C/S(Client/Server)架构两种组成. B/S也就是浏览器/服务器,用户只需要在浏览器中进行相关操作(通常是输入访问地址,或者提

大前端应用开发与架构设计-书籍推荐

大前端应用开发与架构设计-书籍推荐 大前端应用开发与架构设计 在学习新技能(无论是工作还是生活方面),书籍总是呈现知识最完善.系统的方式之一. 接下来将推荐在前端领域的一些著作,如果你想成为一名优秀的前端工程师,那就去好好拜读它们吧. HTML5+CSS3+JavaScript Web设计与前端开发秘籍:HTML CSS JavaScript jQuery 构建网站 HTML 5与CSS 3权威指南(第3版 上册) HTML5基础知识 核心技术与前沿案例 HTML5权威指南 CSS世界 图解CS