
Разработка большого веб-приложения - серьезная проблема на предприятии. Размер команды увеличивается, функции начинают перегружать приложение, качество кода и управление день за днем становятся все жестче. Итак, что может быть хорошим шаблоном проектирования для вашего программного обеспечения в настоящее время. Какая формула может решить вашу проблему и ускорить развитие со временем ..?
Что нам нужно?
- Функциональность разбита на независимые модули меньшего размера.
- Слабосвязанная архитектура.
- Независимость от фреймворка или библиотеки. Гибкость к изменениям в будущем.
- Промежуточный уровень интерпретирует запросы. Модули не имеют прямого доступа к ядру или библиотекам.
- Предотвратить падение приложений из-за ошибок с определенными модулями.
Зачем нам нужны шаблоны дизайна?
- Это многоразовое решение, которое можно применить к часто возникающим проблемам при разработке программного обеспечения.
- Шаблоны бывают проверенные, выразительные, многоразовые и предложить ценность.
- Код становится более выразительным, инкапсулированным и структурированным. .
- При создании или поддержке решений один из самых эффективных подходов к объединению всех разработчиков или групп вашей организации на одной странице создает шаблоны дизайна.
- Одним из наиболее важных аспектов написания поддерживаемого кода является возможность замечать повторяющиеся темы в этом коде и оптимизировать им.
Происхождение узоров?
- Ранние работы архитектора Кристофера Александра
- Он создал язык шаблонов, который помог бы расширить возможности любого, кто желает проектировать и строить в любом масштабе.
- В 1995 году Эрих, Ричард, Ральф и Джон - группа, получившая название Банда четырех ( или GoF для краткости) опубликовал Шаблоны проектирования: элементы многоразового объектно-ориентированного программного обеспечения
Это краткое руководство по шаблону проектирования. Если хотите, то почитайте поподробнее. Настоятельно рекомендую прочитать. Https://addyosmani.com/resources/essentialjsdesignpatterns/book/.
1. Шаблон конструктора
- Конструктор - это специальный метод, используемый для инициализации вновь созданного объекта после того, как для него выделена память.
- В JavaScript почти все является объектом.
- Конструктор может использовать для установки значений свойств и методов элемента при первом создании объекта.
- В Javascript мы можем создавать объекты, используя 3 типа:
var newObject = {};
// or
var newObject = Object.create( Object.prototype );
// or
var newObject = new Object();
Мы можем устанавливать / получать свойства объекта, используя следующие типы:
- Точечная запись
// Set properties newObject.someKey = “Hello World”; // Get properties var value = newObject.someKey;
- Квадратная скобка
// Set properties newObject[“someKey”] = “Hello World”; // Get properties var value = newObject[“someKey”]
- Object.define Подробнее здесь
Object.defineProperty( newObject, “someKey”, {
value: “for more control of the property’s behavior”,
writable: true,
enumerable: true,
configurable: true
});
Базовый конструктор
- JavaScript не поддерживает концепцию классов, но поддерживает специальные функции конструктора, которые работают с объектами.
- При вызове функции-конструктора с ключевым словом «new» функция ведет себя как конструктор.
- ключевое слово this ссылается на новый создаваемый объект.
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
this.toString = function () {
return this.model + " " + this.miles;
};
}
// We can create new instances of the car
var civic = new Car( "Honda Civic", 2009, 20000 );
console.log( civic.toString() );
Но приведенный выше код не сильно оптимизирует
Вы хотели банан, но получили гориллу, держащую банан и все джунгли.
- такие функции, как toString (), переопределяются для каждого из новых объектов, созданных с помощью конструктора Car.
- Это затрудняет наследование.
А вот и прототипы:
- Почти все объекты в JavaScript содержат объект «прототип».
- Когда мы вызываем конструктор JavaScript для создания объекта, все свойства прототипа конструктора становятся доступными для нового объекта.
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
}
// Object.prototype.newMethod
Car.prototype.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
var civic = new Car( "Honda Civic", 2009, 20000 );
console.log( civic.toString() );
2. Шаблон модуля
- Модули - это взаимозаменяемые отдельные части более крупной системы, которые можно легко повторно использовать.
- Модули являются неотъемлемой частью любой надежной архитектуры приложения и обычно помогают сохранять блоки кода проекта как четко разделенными, так и организованными em. >.
Но прежде чем идти дальше, давайте взглянем на IIFE или самовызывающиеся функции
Зачем нам IIFE в JS:
- В JS нет модификаторов доступа.
- Переменные и методы не могут быть общедоступными.
- Переменные и методы не могут быть частными.
- Шаблон Module изначально был определен как способ обеспечить как частную, так и публичную инкапсуляцию для классов в традиционной разработке программного обеспечения.
var myNamespace = (function () {
var myPrivateVar, myPrivateMethod;
myPrivateVar = 0;
myPrivateMethod = function( foo ) {
console.log( foo );
};
return {
myPublicVar: "foo",
myPublicFunction: function( bar ) {
myPrivateVar++;
myPrivateMethod( bar );
}
};
})();
- В шаблоне объявленные переменные доступны только внутри модуля.
- Переменные, определенные в возвращаемом объекте, доступны всем.
- Это позволяет нам имитировать конфиденциальность.
- Это идея истинной инкапсуляции, по крайней мере, с точки зрения JavaScript.
3. Паттерн Сингелтона
- Он ограничивает создание экземпляра класса одним объектом.
- Шаблон Singleton может быть реализован путем создания класса с методом, который создает новый экземпляр класса, если он не существует. Если экземпляр уже существует, он просто возвращает ссылку на этот объект.
- Он служит пространством имен общего ресурса, которое отделяет код реализации от глобального пространства имен, чтобы обеспечить единую точку доступа для функций.
var mySingleton = (function () {
// Instance stores a reference to the Singleton
var instance;
function init() { // Singleton };
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if ( !instance ) { // check for the instance
instance = init(); //
}
return instance;
}
};
})();
4. Образец наблюдателя

Один или несколько наблюдателей интересуются состоянием предмета и регистрируют свой интерес к предмету, присоединяясь к нему. Когда что-то меняется в нашей теме, что может заинтересовать наблюдателя, отправляется сообщение с уведомлением, которое вызывает метод обновления в каждом наблюдателе. Когда наблюдателя больше не интересует состояние субъекта, он может просто отстраниться. Этот паттерн состоит из следующих компонентов:
- Тема: ведет список наблюдателей, упрощает добавление и удаление наблюдателей.
- Наблюдатель: предоставляет интерфейс обновления для объектов, которые должны быть уведомлены об изменениях состояния Субъекта.
- ConcreteSubject: рассылает уведомления наблюдателям об изменениях состояния.
- ConcreteObserver: хранит ссылку на ConcreteSubject, реализует интерфейс обновления для Observer, чтобы гарантировать, что состояние соответствует состоянию Subject.
Прежде всего, мы определяем наблюдателя с функцией обновления. Вы можете написать логику в функции обновления, что хотите делать.
// The Observer
function Observer(){
this.update = function(){
// ...
};
}
Теперь мы пишем ObserverList, которым будет управлять субъект.
function ObserverList(){
this.observerList = [];
}
ObserverList.prototype.add = function( obj ){
return this.observerList.push( obj );
};
ObserverList.prototype.count = function(){
return this.observerList.length;
};
ObserverList.prototype.get = function( index ){
if( index > -1 && index < this.observerList.length ){
return this.observerList[ index ];
}
};
ObserverList.prototype.indexOf = function( obj, startIndex ){
var i = startIndex;
while( i < this.observerList.length ){
if( this.observerList[i] === obj ){
return i;
}
i++;
}
return -1;
};
ObserverList.prototype.removeAt = function( index ){
this.observerList.splice( index, 1 );
};
И напоследок пишем тему:
function Subject(){
this.observers = new ObserverList();
}
Subject.prototype.addObserver = function( observer ){
this.observers.add( observer );
};
Subject.prototype.removeObserver = function( observer ){
this.observers.removeAt( this.observers.indexOf( observer, 0 ) );
};
Subject.prototype.notify = function( context ){
var observerCount = this.observers.count();
for(var i=0; i < observerCount; i++){
this.observers.get(i).update( context );
}
};
Этот шаблон похож на реализацию PubSub, но в PubSub Subject уведомляет наблюдателей, находящихся в теме. Для этого поддерживайте объект темы, содержащий список подписчиков. Это еще один шаг вперед по вышеуказанному шаблону.
5. Шаблон посредника
- В словаре посредник называется нейтральной стороной, которая помогает в переговорах и разрешении конфликтов. В нашем мире посредник - это шаблон поведенческого проектирования, который позволяет нам предоставлять унифицированный интерфейс, через который могут взаимодействовать различные части системы.
- Посредник способствует слабой связи, гарантируя, что вместо того, чтобы компоненты явно ссылаться друг на друга, их взаимодействие обрабатывается через эту центральную точку.
- Реальной аналогией может быть типичная система управления движением в аэропорту. Башня (Посредник) управляет тем, какие самолеты могут взлетать и приземляться, потому что все коммуникации (уведомления, которые прослушиваются или транслируются) осуществляются с самолетов на диспетчерскую вышку, а не с самолета на самолет. Централизованный контроллер - ключ к успеху этой системы, и это действительно роль, которую посредник играет в разработке программного обеспечения.
- Но… Возможно, самым большим недостатком использования шаблона является то, что он может создать единую точку отказа. Размещение посредника между модулями также может вызвать снижение производительности, поскольку они всегда взаимодействуют косвенно. Из-за природы слабой связи сложно определить, как система может реагировать, только глядя на широковещательные передачи.
var orgChart = {
addNewEmployee: function(){
// getEmployeeDetail provides a view that users interact with
var employeeDetail = this.getEmployeeDetail();
// when the employee detail is complete, the mediator (the 'orgchart' object)
// decides what should happen next
employeeDetail.on("complete", function(employee){
// set up additional objects that have additional events, which are used
// by the mediator to do additional things
var managerSelector = this.selectManager(employee);
managerSelector.on("save", function(employee){
employee.save();
});
});
},
}
6. Выкройка прототипа
- Он основан на прототипном наследовании, когда мы создаем объекты, которые действуют как прототипы для других объектов.
- Это требует использования Object.create.
- Стоит отметить, что прототипные отношения могут вызвать проблемы при перечислении свойств объектов и (как рекомендует Крокфорд) заключении содержимого цикла в проверку hasOwnProperty ().
- Стоит отметить, что прототипные отношения могут вызвать проблемы при перечислении свойств объектов и (как рекомендует Крокфорд) заключении содержимого цикла в проверку hasOwnProperty ().
- Object.create также позволяет нам легко реализовывать расширенные концепции, такие как дифференциальное наследование, когда объекты могут напрямую наследовать от других объектов.
var myCar = {
name: "Ford Escort",
drive: function () {
console.log( "Weeee. I'm driving!" );
},
panic: function () {
console.log( "Wait. How do you stop this thing?" );
}
};
// Use Object.create to instantiate a new car
var yourCar = Object.create( myCar );
// Now we can see that one is a prototype of the other
console.log( yourCar.name );
7. Командный шаблон
- Шаблон Command направлен на инкапсуляцию вызовов методов, запросов или операций в один объект и дает нам возможность как параметризовать, так и передавать вызовы методов, которые могут быть выполнены.
- Общая идея, лежащая в основе шаблона Command, заключается в том, что он предоставляет нам средство для разделения ответственности за выдачу команд от всего, что выполняет команды, вместо этого делегируя эту ответственность различным объектам.
(function(){
var carManager = {
// request information
requestInfo: function( model, id ){
return "The information for " + model + " with ID " + id + " is foobar";
},
// purchase the car
buyVehicle: function( model, id ){
return "You have successfully purchased Item " + id + ", a " + model;
},
// arrange a viewing
arrangeViewing: function( model, id ){
return "You have successfully booked a viewing of " + model + " ( " + id + " ) ";
}
};
})();
carManager.execute = function ( name ) {
return carManager[name] && carManager[name].apply( carManager, [].slice.call(arguments, 1) );
};
carManager.execute( "buyVehicle", "Ford Escort", "453543" );
8. Узор фасада
- Удобные высокоуровневые интерфейсы для больших массивов кода, которые скрывают основную сложность
- Когда вы возводите фасад, вы обычно создаете внешний вид, который скрывает иную реальность. Думайте об этом как об упрощении API, представленного другим разработчикам.
var module = (function () {
var _private = {
i: 5,
get: function () {
console.log('current value:' + this.i);
},
set: function (val) {
this.i = val;
},
run: function () {
console.log('running');
},
jump: function () {
console.log('jumping');
}
};
return {
facade: function (args) {
// set values of private properties
_private.set(args.val);
// test setter
_private.get();
// optional: provide a simple interface
// to internal methods through the
// facade signature
if (args.run) {
_private.run();
}
}
}
}());
- Упрощает использование за счет ограниченного, более удобочитаемого API
- Скрывает внутреннюю работу библиотеки. Делает реализацию менее важной.
- Отличается от шаблона модуля, поскольку предоставляемый API может сильно отличаться от определенных общедоступных / частных методов.
9. Шаблон микширования
Миксины - это классы, которые предлагают функциональные возможности, которые могут быть легко унаследованы подклассом или группой подклассов с целью повторного использования функций.
var myMixins = {
moveUp: function(){
console.log( "move up" );
},
moveDown: function(){
console.log( "move down" );
},
stop: function(){
console.log( "stop! in the name of love!" );
}
};
// A skeleton carAnimator constructor
function CarAnimator(){
this.moveLeft = function(){
console.log( "move left" );
};
}
// A skeleton personAnimator constructor
function PersonAnimator(){
this.moveRandomly = function(){ /*..*/ };
}
// Extend both constructors with our Mixin
_.extend( CarAnimator.prototype, myMixins );
_.extend( PersonAnimator.prototype, myMixins );
// Now you can internalize the constructors
Еще для чтения:
- Заводской образец
- Схема наилегчайшего веса
- Шаблон декоратора