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

2018-08-15  本文已影响0人  gz008

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设计一种多文件描述同一个类的方式

关键点

Object.getOwnPropertyDescriptor(obj, prop)
Object.defineProperty(obj, prop, descriptor)

想法

实现

//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() {

    },

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

    },
});

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

上一篇下一篇

猜你喜欢

热点阅读