如何为JavaScript选择OO设计模式 [英] How to choose OO design patterns for JavaScript

查看:75
本文介绍了如何为JavaScript选择OO设计模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

OO我的意思是经典的OO。我一直在定义我的类(javascript没有传统类)之间来回使用模块模式来提供隐私,并使用对象文字来创建公共静态的集合。

By OO I mean classical OO. I keep going back and forth between defining my "classes" ( javascript does not have traditional classes ) using the module pattern to provide privacy and using object literals to create a collection of "public statics".

当我创建类时,我没有指导力,可以让我确定要使用的组织类型。好吧,除了我的代码传递了jshint和jslint w / no选项设置。

I have no guiding force when I create "classes" that lets me determine what type of organization to use. Well, besides the fact that my code passes both jshint and jslint w/ no options set.

我正在使用大约1500行代码,所以我需要一个引导力在代码变得不可管理之前我必须废弃它。

I'm working w/ about 1500 lines of code so I need a "guiding force" before the code becomes un-manageable and I have to scrap it.

我很清楚在JavaScript中编写类的不同方法。那些由Alex MacCaw编写的JavaScript Web应用程序教授以及SO上列出的众多方法。

I am well aware of the different ways to write "classes" in JavaScript. Those taught by JavaScript Web Applications written by Alex MacCaw as well as the numerous ways listed here on SO.

然而,应用程序明智,我只是不知道用什么方法来使用。

However, application wise, I just don't know what method to use.

最简单的似乎是对象文字中的方法和变量的集合,如下所示:

The simplest seems to be a collection of methods and variables in an object literal like this:

var public_statics = {
    public_func: function () {},
    public_var: "hello"
}

最复杂的似乎是 - 一个IIFE。

and the most complicated seems to be - an IIFE.

(function(){
    var private_var;
    function private_func(){
    }
})();

我如何知道使用哪一种或多种中间变体?

How do I know which one to use or the multitude of in-between variations?

一个具体的例子:对于MVC中的控制器怎么样。

For a concrete example: How about for a controller in the MVC.

目前(和一些随机选择的),我实现这样的控制器:

Currently ( and some what randomly chosen), I implement a controller like this:

var Co = {};
Co.Controller = function(){
    // 'classes' from Mo are called here
    // 'classes' from Su are called here
}

然后我将其他与Control相关的方法改为Co。

then I tack on other Control related method to Co.

如何选择使用哪种OO?

How do I choose what style of OO to use?

已更新

我的图书馆目前分为4个名称空间:

My library is currently divided between 4 namespaces:

var Mo = {},
    Vi = {},
    Co = {},
    Su = {};

模型,视图和控制器应该是不言自明的,(Su)pport适用于所有类 不包含在MVC中,例如DOM访问,效果,调试代码等。

Model, View, and Controller should be self-explanatory and (Su)pport is for all "classes" not contained in the MVC, for example DOM access, Effects, Debug code, etc.

我应该使用什么OO样式来进一步组织这个库/代码?

What OO style should I use to further organize this library/code?

控制器类示例:

/**
 **  Controller
 */

Co.Controller = function (o_p) {
    var o_p_string_send;
    Su.time();
    o_p = Mo[o_p.model].pre(o_p);
    if (o_p.result !== 'complete') {
        o_p_string_send = JSON.stringify(o_p);
        Su.time();
        //Su.log(o_p_string_send);
        Co.serverCall('pipe=' + o_p_string_send, function (o_p_string_receive) {
            Su.time();
            //Su.log(o_p_string_receive);
            o_p.server = JSON.parse(o_p_string_receive);
            Mo[o_p.model].post(o_p);
            Su.time(true);
            Su.log('Server time: [' + o_p.server.time + ']');
        });
    }
};


推荐答案

IFFE s经常让人难以阅读和个人阅读,我不知道为什么它们变得如此主流。我认为代码应该易于阅读和简洁。尝试模拟不属于语言规范的语言行为往往是一个非常愚蠢的想法。

IFFEs are often confusing to read and personally, I have no idea why they have become so mainstream. I think code should be easy to read and concise. Attempting to simulate language behavior that is not part of the language specification is often-times a very dumb idea.

例如,JavaScript不支持多重继承,多态或许多其他有趣的范例。所以很多时候,我们看到人们试图在JS中创建这些疯狂的方式,有点像多态或私有成员等。我认为这是一个错误。

For example, JavaScript does not support multiple inheritance, polymorphism, or many other interesting paradigms. So a lot of times, we see people trying to create these crazy ways of sorta'-kinda' having polymorphism or private members, etc in JS. I think this is a mistake.

我目前正在一个高性能JS数据结构库上做一个业余爱好项目(我试图超越谷歌的关闭和一堆其他)。来自C ++和Java背景,我总是喜欢制作东西类,我喜欢继承等等。让我与你分享一些代码片段。起初,我以为我很聪明,因为我写的是这样的东西:

I'm currently working as a sort of hobby project on a high-performance JS data structures library (I'm trying to outperform Google's closure and a bunch of others). Coming from a C++ and Java background, I always like to make stuff classes and I like inheritance, etc, etc. Let me share some code-snippets with you. At first, I thought I was being clever because I was writing stuff like this:

function __namespace(n, v) {
    return {"meta":{"namespace":n,"version":v}};
}

var FJSL = FJSL == undefined ? new __namespace("Fast JavaScript Library", 0.1) : FJSL;

__using = function(parent, child) {
    clazz = new child();
    clazz.super = new parent();
    if (clazz.super == undefined) return clazz;
    for (a in clazz.super) {
        for (b in clazz) {
            if (a == "constructor" || b == "constructor") continue;
            if (clazz[b] === clazz.super[a]) continue;
            if (a == b && typeof clazz[b] != typeof clazz.super[a]) throw "Typesafety breached on '" + a + "' while trying to resolve polymorphic properties."; 
            if (a == b && typeof clazz[b] == typeof clazz.super[a]) {
                clazz["_"+a] = clazz.super[a];
            } else if (clazz[a] == undefined) {
                clazz[a] = clazz.super[a];
            }
        }
    }
    return clazz;
};

我正在使用它(在一个简单的队列示例中):

And I was using it like so (in the example of a simple Queue):

FJSL.Array = function() { 
    this.data = [];

    this.contains = function(idx, element) {
        for (var i = idx; i < this.data.length; i++) {
            if (this.data[i] === element)
                return i;
        }
        return -1;
    }

    this.size = function() {
        return this.data.length;
    }
}

FJSL.Queue = function() {
    return __using(FJSL.Array, 
    function() {
        this.head = 0;
        this.tail = 0;

        this.enqueue = function(element) {
            this.data[this.tail++] = element;
        };

        this.dequeue = function() {
            if (this.tail == this.head)
                return undefined;
            return this.data[this.head++];
        };

        this.peek = function() {
            return this.data[this.head];
        };

        this.size = function() {
            return this.tail - this.head;
        };

        this.contains = function(element) {
            return this._contains(this.head, element);
        };
    }
)};

你会注意到我是如何伪造继承的(Queue使用数组,har har , 我很聪明)。但是,对于 a)阅读 b)理解,这绝对是疯了。我忍不住想起这个模因:

You'll note how I'm sort of faking inheritance (a Queue uses an Array, har har, I'm clever). However, this is absolutely insane to a) read and b) understand. I couldn't help but be reminded of this meme:

让我向您展示功能相同的代码,而不是我尝试进行所有这些花哨的预处理和后处理:

Let me show you functionally equivalent code without me trying to do all this fancy pre- and post-processing:

FJSL.Queue = function(opts) {
    this.options = opts;
    this.head = 0;
    this.tail = 0;
    this.data = [];
};

FJSL.Queue.prototype = {
    add : function(element) {
        this.data[this.tail++] = element;
    },

    enqueue : function(element) {
        this.data[this.tail++] = element;
    },

    dequeue : function() {
        if (this.tail == this.head) {
            return undefined;
        }
        return this.data[this.head++];
    },

    peek : function() {
        return this.data[this.head];
    },

    size : function() {
        return this.tail - this.head;
    },

    contains : function(element) {
        // XXX: for some reason a for : loop doesn't get JIT'ed in Chrome
        for (var i = this.head; i < this.data.length; i++) {
            if (this.data[i] === element) {
                return true;
            }
        }
        return false;
    },

    isEmpty : function() {
        if (size) {
            return true;
        }
        return false
    }, 

    clear : function() {
        this.data = [];
    }
};

显然,我必须为可能使用数组的任何其他结构复制原型构造函数,但是我想要完成的事情是如此清晰,即使是新手JS程序员也可以告诉我们发生了什么。不仅如此,如果人们想要修改代码,他们就知道要去哪里以及做什么。

Obviously, I'd have to duplicate the prototype constructor for any other structures that may use an array, but what I'm trying to accomplish is so much clearer, even a novice JS programmer can tell what's going on. Not only that, but if people want to modify the code, they know exactly where to go and what to do.

我的建议是不要陷入困境试图使JS表现得像C ++或Java的疯狂。它永远不会。是的,你可以伪造继承和私人/公共/受保护的成员,但JS从来没有打算这样做。我认为拥有这种臃肿的代码(试图模拟非标准行为)的影响对高性能网络应用程序及其同类产品非常重要。

My suggestion is don't get caught up in the insanity of trying to make JS behave like C++ or Java. It's never going to. And yeah, you can fake inheritance and private/public/protected members, but JS was never intended for that. I think the repercussion of having this kind of bloated code (that attempts to simulate non-standard behavior) is very taxing on high-performance web-apps and their ilk.

简而言之,我建议使用一个对象字面值:

In short, I suggest using an object literal:

var public_statics = {
    public_func: function () {},
    public_var: "hello"
}

这很容易理解,很容易修改,易于扩展。如果你的系统很脆弱,如果有人意外更改了某些私有变量,就会崩溃和烧毁,你只需要记录它。

It's easy to understand, easy to modify, and easy to extend. If your system is brittle enough to crash and burn if someone accidentally changes some "private" variable, you simply need to document it.

这篇关于如何为JavaScript选择OO设计模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆