实用javascript面向对象设计模式的示例


81

您在应用程序的javascript中使用哪种面向对象的设计模式,为什么?

即使没有附加正式的设计模式,也可以自由发布代码。

我已经写了很多JavaScript,但是我没有在我的工作中应用很多面向对象的模式,所以我肯定会遗漏很多东西。


您可能没有以您可能认为的方式看过经典的OOP。但是,您可能已经将功能与原型OOP结合使用,而从未真正意识到它。
dave

其实我做的(有时)当我使用OOP实现-我想开始使用OOP更加自觉,正是因为我想成为更加审议关于它
铭耀

我投票结束这个问题是离题的,因为它只是询问其他人在其代码中所做的事情。
Almo

Answers:


54

以下是三种流行的JavaScript模式。这些由于闭包而易于实现:

您可能还需要签出:

以下是Diaz在2008年发表的Google I / O演讲,他在书中讨论了一些主题:


真好!咖喱似乎是一种更聪明的方式来做我尝试做的一些概括。已经使用简单形式的模块和备注-但需要研究这些示例以推动我目前的工作方式。您使用最多的是哪几个?
铭耀

@ming:可能是模块模式。它非常易于实现和理解,并且具有一些很酷的功能,包括命名空间和私有变量/方法。
丹尼尔·瓦萨洛

26

遗产

我使用了基于ExtJS 3的继承符号,我发现它的工作方式非常接近于模拟Java中的经典继承。它的基本运行方式如下:

// Create an 'Animal' class by extending
// the 'Object' class with our magic method
var Animal = Object.extend(Object, {
    move : function() {alert('moving...');}
});

// Create a 'Dog' class that extends 'Animal'
var Dog = Object.extend(Animal, {
    bark : function() {alert('woof');}
});

// Instantiate Lassie
var lassie = new Dog();

// She can move and bark!
lassie.move();
lassie.bark();

命名空间

我也同意Eric Miraglia坚持使用名称空间的观点,因此,上面的代码应该在window对象之外的自己的上下文中运行,如果您打算将代码作为在浏览器窗口中执行的许多并发框架/库之一运行,则这至关重要。

这意味着到达窗口对象的唯一方法是通过您自己的名称空间/模块对象:

// Create a namespace / module for your project
window.MyModule = {};

// Commence scope to prevent littering 
// the window object with unwanted variables
(function() {

    var Animal = window.MyModule.Animal = Object.extend(Object, {
         move: function() {alert('moving...');}
    });

    // .. more code

})();

介面

您还可以利用更多高级OOP构造(例如接口)来增强应用程序设计。对此的处理方法是增强Function.prototype,以便按照以下方式获得注释:

var Dog = Object.extend(Animal, {
     bark: function() {
         alert('woof');
     }
     // more methods ..
}).implement(Mammal, Carnivore);

OO模式

至于Java的“模式”,我发现它仅用于Singleton模式(非常适合缓存)和Observer模式用于事件驱动的功能,例如在用户单击按钮时分配一些操作。

利用观察者模式的一个例子是:

// Instantiate object
var lassie = new Animal('Lassie');

// Register listener
lassie.on('eat', function(food) {
   this.food += food;
});

// Feed lassie by triggering listener
$('#feeding-button').click(function() {
    var food = prompt('How many food units should we give lassie?');
    lassie.trigger('eat', [food]);
    alert('Lassie has already eaten ' + lassie.food + ' units');
});

那只是我的OO JS包中的几个技巧,希望它们对您有用。

如果您打算走这条路,我建议您阅读Douglas Crockfords Javascript:The Good Parts。这是一本精采的书。


20

我是Module Pattern的粉丝。这是一种实现可扩展的,非依赖的(大多数情况下)框架的方法。

例:

框架Q定义如下:

var Q = {};

要添加功能:

Q.test = function(){};

这两行代码一起用于形成模块。在这种情况下Q,模块背后的思想是它们都扩展了一些基本框架,但彼此之间并不依赖(如果设计正确),可以以任何顺序包含在内。

在模块中,首先创建框架对象(如果不存在)(这是Singleton模式的示例):

if (!Q)
    var Q = {};

Q.myFunction = function(){};

这样,您可以在单独的文件中拥有多个模块(如上面的模块),并以任何顺序包含它们。他们中的任何一个都会创建框架对象,然后对其进行扩展。无需手动检查框架是否存在。然后,检查自定义代码中是否存在模块/功能:

if (Q.myFunction)
    Q.myFunction();
else
    // Use a different approach/method

1
这看起来非常有用。您如何在代码中使用它?感谢分享!
铭耀

我在最近的一个项目中使用了该项目,在该项目中,我有用于共同功能,UI和其他两个专用机制的单独的JavaScript文件。所有文件都将功能添加到同一框架(使用上面显示的方法定义)中,并且它们像上面一样调用这些功能。
克里斯·

这种技术的主要用途之一是避免污染全局名称空间。还有什么污染呢?一个Q框架变量,还是数十个函数和变量?
克里斯·拉普兰特


4

我真的很喜欢jquery的方法链接模式,它允许您在一个对象上调用多个方法。它使得在一行代码中执行多个操作确实非常容易。

例:

$('#nav').click(function() {
   $(this).css('color','#f00').fadeOut();
});

对-同意!您是否曾经开发过以这种方式工作的自定义方法?
铭耀

3

我真的很喜欢带有jQuery插件的Decorator模式。与其修改插件来满足您的需求,不如编写一个自定义插件来转发请求并添加其他参数和功能。

例如,如果你需要传递一组周围所有的时间默认参数,你需要稍微不同的行为关系到业务逻辑,写一个插件,做什么prepost工作是必要的,以满足您的需求,并通过您的默认参数如果未指定这些特定参数。

这样做的主要好处是您可以更新库,而不必担心移植库更改。您的代码可能会中断,但至少有可能不会中断。


这听起来是个好主意。您在代码上有一个实际的例子来进行实际的扩展吗?即使是一个简单的示例也可以极大地帮助所有人。
铭耀

3

在javascript世界中,有用的模式之一是链模式,该模式最初由LINQ流行,并在jQuery中使用。

这种模式使我们能够以链接的方式调用类的不同方法。

这种模式的主要结构是

var Calaculator = function (init) {
    var result = 0;
    this.add = function (x) { result += (init + x); return this; };
    this.sub = function (x) { result += (init - x); return this; };
    this.mul = function (x) { result += (init * x); return this; };
    this.div = function (x) { result += (init / x); return this; };

    this.equals = function (callback) {
        callback(result);
    }

    return this;
};


new Calaculator(0)
    .add(10)
    .mul(2)
    .sub(5)
    .div(3)
    .equals(function (result) {
        console.log(result);
    });

该模式的关键思想是this关键词,它使访问计算器功能的其他公共成员成为可能。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.