zoukankan      html  css  js  c++  java
  • 组件模式代码实践(C#版本)

    此测试代码包含3个基本类:

    class EntityBase:实体基类

    class ComponentBase:组件基类

    class Event:消息类

    组合模式的关键在于:(1)实体通过组件实现功能,组件依赖于实体而存在;(2)通过事件驱动组件的各种行为。

    EntityBase代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace TestComponentModel
    {
        class EntityBase
        {
            // 组件列表,未实现RTTI,故用string做索引
            // 如果有RTTI,可以直接存储List<ComponentBase>,并且大多是这么做的
            Dictionary<string, ComponentBase> ComponentArray = new Dictionary<string, ComponentBase>();
    
            // 通过此函数将消息分发给各个Component,各个Component各自处理此消息
            // 通过DisptachEvetn,每个Compoent都会收到此消息,但是否处理此消息,由各组件自己决定
            public virtual bool DispatchEvent(Event evt)
            {
                bool bHandled = false;
                foreach (ComponentBase comp in ComponentArray.Values)
                {
                    bool ret = comp.OnEvent(evt);
                    bHandled = (bHandled || ret);
                }
                if (bHandled == false)
                    Console.WriteLine("Receive an unhandled event: id = " + evt.EventID.ToString());
    
                return bHandled;
            }
    
            public bool AddComponent(string compName, ComponentBase compObject)
            {
                if (compObject == null)
                {
                    Console.Write("AddComponent Failed, Component.Name=" + compName);
                    return false;
                }
    
                ComponentArray.Add(compName, compObject);
                compObject.OnAttachToEntity(this);
                OnComponentAttached(compObject);
    
                return true;
            }
    
            public bool RemoveComponent(string compName)
            {
                if (!ComponentArray.ContainsKey(compName))
                {
                    Console.Write("RemoveComponent Failed, Component.Name=" + compName);
                    return false;
                }
    
                ComponentArray[compName].OnDetachFromEntity(this);
                OnComponentDetached(ComponentArray[compName]);
                ComponentArray.Remove(compName);
                return true;
            }
    
            public virtual void OnComponentAttached(ComponentBase compObject)
            {
            }
    
            public virtual void OnComponentDetached(ComponentBase compObject)
            {
            }
    
        }
    }

    ComponentBase代码:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace TestComponentModel
    {
        class ComponentBase
        {
            protected delegate void EventHandleFunction(Event evt);
    
            private EntityBase Owner = null;
            // 事件映射表
            private Dictionary<int, EventHandleFunction> EventHandlerMap = new Dictionary<int, EventHandleFunction>();
    
            public virtual bool OnEvent(Event evt)
            {
                EventHandleFunction function = null;
                if(EventHandlerMap.TryGetValue(evt.EventID, out function) == false)
                {
                    return false;
                }
    
                if (function == null)
                    return false;
    
                function(evt);
                return true;
            }
    
            public virtual void OnAttachToEntity(EntityBase ety)
            {
                Owner = ety;
            }
    
            public virtual void OnDetachFromEntity(EntityBase ety)
            {
                Owner = null;
            }
    
            // 注册事件处理函数,同一事件注册两次,则后面的覆盖前面的
            protected void RegisterEvent(int eventID, EventHandleFunction handlerFunc)
            {
                if (EventHandlerMap.ContainsKey(eventID))
                    EventHandlerMap.Remove(eventID);
                EventHandlerMap.Add(eventID, handlerFunc);
            }
    
            protected void UnregiterEvent(int eventID)
            {
                if (EventHandlerMap.ContainsKey(eventID))
                    EventHandlerMap.Remove(eventID);
            }
        }
    }

    Event代码:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace TestComponentModel
    {
        class Event
        {
            public int EventID = -1;
            public ArrayList EventArgs = new ArrayList();
    
            public void PushUserData<T>(T data)
            {
                EventArgs.Add(data);
            }
    
            public T GetUserData<T>(int index)
            {
                if (index >= EventArgs.Count)
                {
                    Console.Write("GetUserData Error!");
                    return default(T);
                }
                return (T)EventArgs[index];
            }
        }
    }

    测试代码包括Main.cs、一个继承自ComponentBase的组件TestComponent和一个事件定义的类EventDefines。

    EventDefines代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace TestComponentModel
    {
        public enum EventDefines
        {
            Event_01 = 0,
            Event_02,
            Event_03,
        }
    }

    TestComponent代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace TestComponentModel
    {
        class TestComponent : ComponentBase
        {
            public override void OnAttachToEntity(EntityBase ety)
            {
                base.OnAttachToEntity(ety);
    
                // 注册事件响应函数
                RegisterEvent((int)EventDefines.Event_01, DealEvent01);
                RegisterEvent((int)EventDefines.Event_03, DealEvent03);
            }
    
            public override void OnDetachFromEntity(EntityBase ety)
            {
                base.OnDetachFromEntity(ety);
            }
    
            private void DealEvent01(Event evt)
            {
                string evtData = evt.GetUserData<string>(0);
                Console.WriteLine("TestComponent Handle Event: ID = " + evt.EventID.ToString());
                Console.WriteLine("TestComponent Handle Event: Data = " + evtData);
            }
    
            private void DealEvent03(Event evt)
            {
                float evtData = evt.GetUserData<float>(0);
                Console.WriteLine("TestComponent Handle Event: ID = " + evt.EventID.ToString());
                Console.WriteLine("TestComponent Handle Event: Data = " + evtData);
            }
        }
    }

    Main.cs代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace TestComponentModel
    {
        class Program
        {
            static void Main(string[] args)
            {
                // 构造一个EntityBase对象
                EntityBase ety = new EntityBase();
                // 添加TestComponent组件,可以移到EntityBase的继承类的构造函数中
                TestComponent testComp = new TestComponent();
                ety.AddComponent("TestComponent", testComp);
    
                // 发送消息Event_01
                Event evt1 = new Event();
                evt1.EventID = (int)EventDefines.Event_01;
                evt1.PushUserData<string>("SomeData For Event01");
                ety.DispatchEvent(evt1);
    
                // 发送消息Event_02
                Event evt2 = new Event();
                evt2.EventID = (int)EventDefines.Event_02;
                evt2.PushUserData<string>("SomeData For Event02");
                ety.DispatchEvent(evt2);
    
                // 发送消息Event_03
                Event evt3 = new Event();
                evt3.EventID = (int)EventDefines.Event_03;
                evt3.PushUserData<float>(0.123f);
                ety.DispatchEvent(evt3);
    
                Console.Read();
            }
        }
    }

     运行结果截图:

    组合模式是实用性很强的一种设计模式,目前在各种游戏代码中广泛存在,熟练运用此模式可以使代码简洁高效、可读易修改并且查错方便。

    本例子所提供的代码只是测试代码,若想应用于项目,需根据实际情况进行一些修改。不过,改来改去,思想始终不变。

    PS:所谓模式,即代码的组织方式,模式源于实践和总结。同时,模式也是一种思想,是人们对于程序对象的一种认识和剖析...

  • 相关阅读:
    更准确的mysql全文索引
    range
    牛顿冷却定律 使用
    Servo: The Embeddable Browser Engine
    Node.js V0.12新特性之性能优化
    Lodash,你正在使用的JavaScript库
    Python on Android
    Microsoft HoloLens 技术解谜(下)
    Microsoft HoloLens 技术解谜(上)
    市售体感设备横评
  • 原文地址:https://www.cnblogs.com/sifenkesi/p/2468060.html
Copyright © 2011-2022 走看看