Примеры практических шаблонов объектно-ориентированного проектирования javascript


81

Какие шаблоны объектно-ориентированного проектирования вы используете в javascript вашего приложения и почему?

Не стесняйтесь размещать код, даже если к нему не прикреплен официальный шаблон дизайна.

Я написал много javascript, но не применил много объектно-ориентированных шаблонов к тому, что делаю, и я уверен, что многого не хватает.


Вы, вероятно, не видели классического ООП в том смысле, в котором вы могли бы подумать. Однако вы, вероятно, использовали функции прототипа ООП и просто никогда не осознавали этого.
Дэйв

Я действительно (иногда) понимаю, что когда использую ООП, я хочу начать использовать ООП гораздо более осознанно именно потому, что я хочу быть более осознанным в этом отношении
ming yeow

Я голосую за то, чтобы закрыть этот вопрос как не по теме, потому что он просто запрашивает список вещей, которые другие люди делают в своем коде.
Almo

Ответы:


54

Ниже приведены три популярных шаблона JavaScript. Их легко реализовать из-за закрытий :

Вы также можете проверить:

Следующее - это выступление Google I / O за 2008 год, представленное Диазом, в котором он обсуждает некоторые темы из своей книги:


отлично! карри выглядит как более умный способ сделать некоторые обобщения, которые я пытался сделать. уже использую простые формы модуля и мемоизации, но мне нужно изучить эти примеры, чтобы понять, как я сейчас это делаю. Какие из них вы используете больше всего?
ming yeow

@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();

Пространства имён

Я также согласен с Эриком Мираглиа в том, что он придерживается пространств имен, поэтому приведенный выше код должен запускаться в своем собственном контексте за пределами объекта окна, это важно, если вы собираетесь запускать свой код как одну из многих параллельных фреймворков / библиотек, выполняющихся в окне браузера.

Это означает, что единственный путь к объекту окна - через ваш собственный объект пространства имен / модуля:

// 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

})();

Интерфейсы

Вы также можете использовать более продвинутые конструкции ООП, такие как интерфейсы, для улучшения дизайна вашего приложения. Мой подход к ним состоит в том, чтобы улучшить Function.prototypeобозначение в следующих строках:

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

ОО шаблоны

Что касается «шаблонов» в смысле 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

Я фанат Модульного паттерна . Это способ реализации расширяемых, независимых (в большинстве случаев) фреймворков.

Пример:

Фреймворк 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
Это выглядит чрезвычайно полезным. как вы используете это в своем коде? Спасибо, что поделился!
ming yeow

Я использовал его в недавнем проекте, где у меня были отдельные файлы JavaScript для общих функций, пользовательского интерфейса и двух других специализированных механизмов. Все файлы добавляли функции в одну и ту же структуру (определенную с использованием метода, который я показал выше), и они вызывали функции, как я сделал выше.
Крис Лапланте,

Одно из основных применений этого типа техники - предотвращение загрязнения глобального пространства имен. Что загрязняет больше? Одна Qпеременная фреймворка или десятки и десятки функций и переменных?
Крис Лапланте,

6

Шаблон singleton часто очень полезен для «инкапсуляции» и организации вещей. Вы даже можете изменить доступность.

var myInstance = {
  method1: function () {
    // ...
  },
  method2: function () {
    // ...
  }
};

самый чистый способ реализовать синглтон в javascript


потрясающе - это тот, который я использую все время! Но это примерно степень моего объектно-ориентированного программирования на javascript. ;)
ming yeow

4

Мне очень нравится шаблон цепочки методов jquery , позволяющий вызывать несколько методов для одного объекта. Это позволяет легко выполнять несколько операций в одной строке кода.

Пример:

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

правильно - согласился! Разработали ли вы свои собственные методы, которые работают таким образом раньше?
ming yeow

3

Мне очень нравится шаблон Decorator с плагинами jQuery. Вместо того, чтобы изменять плагины в соответствии с вашими потребностями, напишите собственный плагин, который просто перенаправляет запросы и добавляет дополнительные параметры и функции.

Например, если вам нужно постоянно передавать набор аргументов по умолчанию, и вам нужно несколько иное поведение, которое связано с бизнес-логикой, напишите плагин, который делает все, что необходимо, preи postработает, чтобы удовлетворить ваши потребности, и передает ваши аргументы по умолчанию если эти конкретные аргументы не указаны.

Основное преимущество этого заключается в том, что вы можете обновлять свои библиотеки и не беспокоиться о переносе изменений библиотеки. Ваш код может сломаться, но есть шанс, что это не так.


Звучит как отличная идея. У вас есть реальный пример кода для фактического расширения? Даже простой пример всем очень поможет.
ming yeow

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ключевое слово, которое делает возможным доступ к другому публичному члену функции Calculator.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.