我如何重构此代码以更加面向对象?

时间:2011-03-08 15:12:19

标签: javascript jquery oop refactoring

更新

因此,我遵循了“justkt”和“xtofl”的建议,并对我的代码进行了一些重大更改。我认为这是一个更好的设计,但请仍然提供反馈和改进建议。

首先,我创建了一些枚举...

var SymbolName = {
    alpha : 0,
    beta : 1,
    // ... etc...
};
Object.freeze(SymbolName);

var TypeOfSymbol = {
    GreekSymbol : 0,
    // ... etc...
};
Object.freeze(TypeOfSymbol);

...然后我通过取出我以前的所有成员变量并将其变成一个记住每Symbol个4个值的对象来重构我的Symbol类...

function Symbol(name, id, value, type) {

    var name = name;
    var id = id;
    var value = value;
    var type = type;

    this.getName = function() {
        return name;
    };

    this.getID = function() {

        return id;
    };

    this.getValue = function() {

        return value;
    };

    this.getMathMLTag = function() {

        var tag;
        switch (Number(type)) {

            case TypeOfSymbol.GreekSymbol:

                tag = 'mi';
                break;

            default:

                tag = 'mo';
                break;
        }
        return tag; 
    };
};

现在,为了创建和访问这些Symbol个对象,我创建了一个Symbols对象,其中包含所有可能Symbol个对象的数组......

function Symbols() {

    var theSymbols = new Array();

    // new Symbol(name, id, value, type)
    theSymbols[SymbolName.alpha] = new Symbol('alpha', 'symbol_' + SymbolName.alpha, 'α', TypeOfSymbol.GreekSymbol);
    // ... etc...

    this.getSymbol = function(symbolID) {

        return theSymbols[symbolID];
    };
};

所以现在一切都很简单。我声明了一个变量var symbols = new Symbols();,如果我想得到符号,我可以这样做:

symbols.getSymbol(SymbolName.alpha); // get the Symbol object
symbols.getSymbol(SymbolName.alpha).getValue(); // get the Symbol value
symbols.getSymbol(SymbolName.alpha).getID(); // get the Symbol ID

这很容易让我轻松地为每个<div>创建Symbol

$.fn.AppendGreekSymbols = function() {
    var symbol;
    var mathTag;
    var openingTags;
    var closingTags;

    // lower-case Greek Alphabet
    var index = SymbolRanges.GreekSymbolsStartIndex;

    for (index; index <= SymbolRanges.GreekSymbolsEndIndex; index++) {

        symbol = symbols.getSymbol(index);

        openingTags = '<div id=\"' + symbol.getID() + '\" class=\"symbol ' + symbol.getName() + '\">';
        mathTag = '<math display=\"block\"><' + symbol.getMathMLTag() + '>';
        closingTags = '</' + symbol.getMathMLTag() + '></math></div>';

        $('.greek-symbols').append(openingTags + mathTag + symbol.getValue() + closingTags);
    }
};

此外,我可以轻松地为所有Symbol个对象定义1个点击处理程序:

$(function() {

    $('div.symbol').click(function() {

        var targetSymbolID = $(this).attr('id').split('_')[1];
        var symbol = symbols.getSymbol(targetSymbolID);
        $().InsertSymbol(symbol);
    });
});

......就是这样!好极了!我认为这是一个很大的变化......我为这个重构过程和我提出的设计感到非常自豪。你们觉得怎么样?

原帖

我有一个Symbol类看起来像这样:

function Symbol() {
    // I need to define some functions in here  
};
Symbol.prototype.alpha = "&#x03B1;";
Symbol.prototype.Alpha = "A";
Symbol.prototype.beta = "&#x03B2;";
Symbol.prototype.Beta = "B";
Symbol.prototype.gamma = "&#x03B3;";
Symbol.prototype.Gamma = "&#x0393;";
Symbol.prototype.delta = "&#x03B4;";
Symbol.prototype.Delta = "&#x0394;";
... and so on for nearly 500 symbols...

每个符号将单独放入其自己的<div class="symbol alpha">元素中,但alpha将是与符号名称对应的类名...所以还有其他类似的元素,例如{{ 1}},<div class="symbol beta">等等......为此,我会有很多重复的代码:

<div class="symbol gamma">

现在,我想要做的是为每个符号及其相应的var symbol = new Symbol(); $('.greek-symbols').append('<div class="symbol alpha">' + symbol.alpha + '</div>'); $('.greek-symbols').append('<div class="symbol beta">' + symbol.beta + '</div>'); $('.greek-symbols').append('<div class="symbol gamma">' + symbol.gamma + '</div>'); ... etc... 容器设置一个click事件处理程序。同样,我会有很多重复的代码,如下:

<div>

我认为有更好的方法可以做到这一点。理想情况下,我希望只有一个事件处理程序可以从类中解析出符号名称,在$('div.symbol.alpha').click(function() { $().InsertSymbol(symbol.alpha); }); $('div.symbol.beta').click(function() { $().InsertSymbol(symbol.beta); }); ... and so on... 类中查找,然后以这种方式工作。所以......

Symbol

...在$('div.symbol').click(function() { // I know the following code doesn't correctly parse out the correct class, // I'll worry about that later, but the idea is clear var symbolName = $(this).attr('class'); // parse out the correct class, the symbol name $().InsertSymbol(Symbol.getSymbol(symbolName)); }); 类中,我会使用这个Symbol函数来获取名称并查找符号并返回正确的符号。但是,我不确定如何在JavaScript / jQuery中执行此操作。我该如何设置这个逻辑?我不知道JavaScript是否有一个HashMap类,就像Java一样,那么查找这些符号的好方法是什么?

如果我需要进一步澄清,请告诉我。

P.S。我欢迎任何有关良好的面向对象设计的来源/参考的建议

5 个答案:

答案 0 :(得分:3)

Javascript有时称为associative arrays,但最常见的是Javascript object literals。在对象文字下面,“values”包含你的键(类名)和值(符号)。

function Symbol() {
    // I need to define some functions in here  
};
Symbol.prototype.values = {
    alpha: "&#x03B1;",
    beta: "&#x03B2;",
    gamma: "&#x03B3;",
    // ...and so on

}; 

或者你可以这样做:

function Symbol() {
    // I need to define some functions in here  
};
Symbol["alpha"] = "&#x03B1;";
Symbol["beta"] = "&#x03B2;";
Symbol["gamma"] = "&#x03B3;";
// ...and so on

我建议使用一个符号类和一个SYMBOLNAME的id(例如alpha),而不是让你的div有一个“符号SYMBOLNAME”类。当然,只有当您的符号对于页面是唯一的时,这才有效。鉴于此,您将检索该值:

$('div.symbol').click(function() {
    var symbolName = this.id; // get the symbol name from the ID
    $().InsertSymbol(Symbol.values[symbolName]);
    // or in case of the second option, $().InsertSymbol(Symbol.[symbolName]);
});

答案 1 :(得分:3)

您可以从面向对象的方法中受益: 如果你定义一个Symbol类,它可能会有很多实例,而不是成员变量

注意:代码尚未经过测试 - 抓住这个想法。

编辑:jsfiddle在http://jsfiddle.net/xtofl/ttjZw/4/

// the class:
function Symbol( name, lowname, upcase, lowcase ) {
   this.name = name;
   this.lowname = lowname;
   this.upcase=upcase;
   this.lowcase=lowcase;
}
// creates a div - may be done using jQuery DOM functions
Symbol.prototype.makedivs = function() {
   return "<div class='"+this->name+"'>"+this.upcase+"</div>"
         +"<div class='"+this->lowname+"'>"+this.lowcase+"</div>"
}
Symbol.prototype.addhandler = function() {
   var symbol = this;
   $(this->name).click()( function(e){ document.write( symbol->upcase ); } );
}



$(document).ready( function() {

  // the instances:
  var symbols = [
    new Symbol( 'alfa', 'Alfa', "&#x03B1;", "&#x03B1;" ),
    new Symbol( 'beta', 'Beta', "&#x03B1;", "&#x03B1;" ),
    //...
  ];
  for( var i = 0; i != symbols.length; ++i ) {
    symbols[i].addhandler();  
  }

});

答案 2 :(得分:2)

$.fn.page = function() {
  window.page = this;

  this.symbols = {
    'alpha': ['A',"&#x03B1;"],
    //etc
  }

  this.delegate('div.symbol', 'click', function(event) {
    var div = $(event.target),
        // parse symbol name from class
        symbolClass = $(this).attr('class').replace('symbol',''),
        // fetch map 
        map = page.symbols[symbolClass],
        // replace text
        newText = div.text().replace(map[0],map[1]);
    div.text(newText);    
  });

};

$(document).ready(function() {
  $(body).page(); // use the most specific selector that contains all your divs
});

答案 3 :(得分:1)

使用jQuery,我想出了以下代码。它并没有真正看到你提到的Symbol类,但你可以根据需要轻松地将符号移动到:

var symbols = {
    'alpha': 'a',
    'beta': 'b'
};

$(document).ready(function(){
    $('div.symbol').each(function(){
        var $this = $(this);
        var classes = $this.attr('class').split(' ');
        $(classes).each(function(ix, cls){
            if(typeof(symbols[cls]) == 'undefined'){ return; }
            $this.html(symbols[cls]);
            return;
        });
    });
});

这说明了使用类名,并且在未知类上不会失败。请注意,我使用$.each代替$.click作为示例。但是,这将在它匹配的每个类上表现,所以如果你有<div class="symbol alpha beta"></div>它将同时适用于alpha和beta!

此处提供代码:http://jsfiddle.net/w3ajG/

答案 4 :(得分:0)

var symbols = {'alpha': "&#x03B1;"};是一种更好的做法,然后你可以轻松访问它们,例如symbols.alpha dnt使其复杂化,

然后

var symbols = {
        'alpha': "&#x03B1;",
        'beta' : "&#x03B2;",
};
$('div.symbol.alpha').click(function() {
      //alert(symbols.alpha); // console.debug(symbols.alpha);
      //or
      //alert(symbols['alpha']); // console.debug(symbols['alpha']);
});