美文网首页
Cocos Creator设计方便维护的面向对象结构的一种方式

Cocos Creator设计方便维护的面向对象结构的一种方式

作者: gz008 | 来源:发表于2018-08-15 20:38 被阅读0次

    1.通常的写一个类的方式

    cc.Class({
    
        extends: cc.Component,
    
        properties: {
            label: {
                default: null,
                type: cc.Label
            },
            // defaults, set visually when attaching this script to the Canvas
            text: 'Hello, World!'
        },
    
        // use this for initialization
        onLoad: function () {
            this.label.string = this.text;
        },
    
        // called every frame
        update: function (dt) {
    
        },
    
        //设置UI相关函数
        showHello() {
    
        },
        
        //触摸事件相关函数
        onTouchHello() {
    
        },
        
        //网络消息相关函数
        onMsgHello() {
    
        },
    
    });
    

    缺陷
    通常来说,一个类里面会包含不止一个showXXX()onTouchXXX()onMsgXXX(),这样会导致这个类文件过于庞大,可能一个类会包含几千行代码,找某个东西的时候不是很清晰,那么如何解决这个问题?

    2.C++里面一般会如何维护一个庞大的类

    HelloWorld.png
    //HelloWorld.h
    #ifndef __HELLOWORLD_SCENE_H__
    #define __HELLOWORLD_SCENE_H__
    
    #include "cocos2d.h"
    
    class HelloWorld : public cocos2d::Scene
    {
    public:
    
        static cocos2d::Scene* scene();
    
        ...
    
        //
        void showHello();
    
        //
        void onTouchHello(Ref* sender);
    
        //
        void onMsgHello();
    
    };
    
    #endif // __HELLOWORLD_SCENE_H__
    
    
    //HelloWorld.cpp
    #include "HelloWorld.h"
    
    Scene* HelloWorld::scene()
    {
         return HelloWorld::create();
    }
    
    //HelloWorldShowUI.cpp
    #include "HelloWorld.h"
    
    void HelloWorld::showHello()
    {
    
    }
    
    //HelloWorldTouchEvent.cpp
    #include "HelloWorld.h"
    
    void HelloWorld::onTouchHello(Ref* sender)
    {
        
    }
    
    //HelloWorldMsgCallfunc.cpp
    #include "HelloWorld.h"
    
    void HelloWorld::onMsgHello()
    {
    
    }
    

    如上所示,我们可以把一个类分成多个文件,不同的文件对应不同种类的相关函数,这样的话,寻找相应的函数就会方便很多。那么,如何用JS实现这种多文件描述同一个类结构?

    3.JS设计一种多文件描述同一个类的方式

    关键点

    • JS的实例可以获取成员的定义
    Object.getOwnPropertyDescriptor(obj, prop)
    
    • JS的实例可以动态增加成员
    Object.defineProperty(obj, prop, descriptor)
    

    想法

    • HelloWorld的每个种类(showXXX、onTouchXXX、onMsgXXX)的函数的集合分别组成一个类
    • HelloWorld构造函数里面,获取其他文件中的函数属性并定义到自身原型链中

    实现

    • 脚本的文件结构


      脚本文件结构
    //HelloWorld.js
    cc.Class({
        extends: cc.Component,
    
        properties: {
            label: {
                default: null,
                type: cc.Label
            },
            // defaults, set visually when attaching this script to the Canvas
            text: 'Hello, World!'
        },
    
        // use this for initialization
        onLoad: function () {
            this.showHello()
        },
    
        // called every frame
        update: function (dt) {
    
        },
    
    });
    
    //HelloWorldShowUI.js
    cc.Class({
        extends: cc.Component,
    
        properties: {
        },
        
        showHello() {
            this.label.string = this.text;
        },
    });
    
    //HelloWorldTouchEvent.js
    cc.Class({
        extends: cc.Component,
    
        properties: {
        },
        
        onTouchHello() {
    
        },
    
    });
    
    //HelloWorldMsgCallfunc.js
    cc.Class({
        extends: cc.Component,
    
        properties: {
        },
        
        onMsgHello() {
    
        },
    
    });
    
    • HelloWorld构造函数或onLoad里面导入其他文件
    cc.Class({
        extends: cc.Component,
    
        properties: {
            label: {
                default: null,
                type: cc.Label
            },
            // defaults, set visually when attaching this script to the Canvas
            text: 'Hello, World!'
        },
    
        // use this for initialization
        onLoad: function () {
            //提取其他文件中的函数到当前对象
            let scripts = [
                'HelloWorldShowUI',
                'HelloWorldMsgCallfunc',
                'HelloWorldTouchEvent',
            ]
            for (let i = 0; i < scripts.length; i++) {
                let script = scripts[i]
                let cls = require(script)
                let instance = new cls()
                this.transferProto2Object(this, instance)
            }
            this.showHello()
        },
    
        // called every frame
        update: function (dt) {
    
        },
        
        //导入其他类中的属性到当前实例
        //每个类都支持继承,且最终必须继承自cc.Component,把cc.Component当成探索终点
        transferProto2Object: function (obj, instance) {
            let regex3 = new RegExp('__\\w+__')  
            let proto = instance.__proto__
            //最大搜索深度3,即当前只能继承一次
            let afterfilter = []
            let inherit = 3
            for (let i = 0; i < inherit; i++) {
                if (proto.__classname__ != 'cc.Component') {
                    //过滤系统函数
                    let notsystem = Object.keys(proto)
                    // cc.log("notsystem = ", notsystem)
                    for (let i =0; i < notsystem.length; i++) {
                        let test = regex3.test(notsystem[i])
                        if (!test) {
                            let descriptor = Object.getOwnPropertyDescriptor(proto, notsystem[i])
                            afterfilter.push({
                                name: notsystem[i],
                                descriptor: descriptor,
                            })
                        }
                    }
                    proto = proto.__proto__
                } else {
                    break
                }
            }
            //定义到当前类对象
            for (;;) {
                if (afterfilter.length == 0) {
                    break
                }
                let element = afterfilter.pop()
                Object.defineProperty(obj.__proto__, element.name, element.descriptor)          
            }
    
        },
    });
    

    缺陷
    节点的触摸事件必须使用代码注册,无法使用拖拽方式

    相关文章

      网友评论

          本文标题:Cocos Creator设计方便维护的面向对象结构的一种方式

          本文链接:https://www.haomeiwen.com/subject/qdrbbftx.html