Автор: Сяофей Данная статья является оригинальной, просьба указывать автора и источник для перепечатки
Во внутренних языках широко используются шаблоны проектирования. Например, общий фабричный шаблон, шаблон декоратора, шаблон синглтона и шаблон итератора в Spring. Но в повседневной фронтенд-разработке шаблоны проектирования используются редко, или каждый код следует определенному шаблону проектирования, но мы этого не знаем. Существует 23 распространенных шаблона проектирования.Если вы просто напишете эту статью в виде названия шаблона + объяснения существительного, она может быть слишком скучной или трудной для понимания и запоминания, поэтому я планирую изменить ее. Ниже мы начнем нашу сегодняшнюю статью с примера.
Предположим, у нас есть такое требование:
let page = {
init: ()=>{
//此处(placeA)有很多业务代码或者调用了很多page中的其他初始化函数
},
....
};
Теперь, когда бизнес итерируется, нам нужно добавить некоторые функции в конец блока кода инициализации page.init(), не затрагивая исходные функции. В обычном письме мы могли бы написать что-то вроде этого:
let page = {
init: ()=>{
//placeA
page.newFunction();
},
newFunction: ()=>{
...
}
};
Написание таким образом может решить наши потребности, но такой код является инвазивным, и мы должны добавить нужный нам код в соответствующее место исходного кода. Но мы думаем о проблеме, если мы используем плагин или код, который был некрасивым и минимизированным, как мы можем найти правильное место для добавления нужных нам функций? Вы можете сначала подумать об этом сами, а затем посмотреть следующий контент.
Сначала давайте посмотрим на решение, а затем подумаем, что за ним стоит.
//我们可以在Function的原型链上定义一个扩展函数,以实现我们的需求。
Function.prototype.fnAfter = function(fn) {
var _self = this;
return function() {
_self.apply(this, arguments);
fn.apply(this, arguments);
}
};
page.init = (page.init || function() {}).fnAfter(function() {
console.log('我们要追加的功能成功啦~');
});
page.init();
Приведенный выше код смог удовлетворить наши потребности, но он недостаточно хорош или может быть написан более гибко. Поскольку я надеюсь, что смогу сделать как цепной вызов jquery, вы всегда можете добавить новые функции в конец. Затем мы можем расширить на основе приведенного выше кода.Это на самом деле очень просто.Нам просто нужно вернуть себя в Function.prototype.fnAfter.
Function.prototype.fnAfter = function(fn) {
var _self = this;
return function() {
var fnOrigin = _self.apply(this, arguments);
fn.apply(this, arguments);
return fnOrigin;
}
};
На самом деле приведенный выше код все еще можно оптимизировать. Например:
//每次扩展的时候我们都需要这么写
page.init = (page.init || function() {}).fnAfter(function() {
//...
});
//我们能不能再优化下,比如容错代码 || function(){} 在一个地方统一处理
//或者我们新建一个工厂函数来帮我们统一做这样的事情,这里我们就不展开了,文章篇幅有限。
Наше выше расширение фактически следует принципу открытого-закрытого (OCP) в объектно-ориентированном программировании. Официальное объяснение OCP заключается в том, что программные объекты (классы, модули, функции...) должны быть расширяемыми, но не модифицируемыми. В шаблоне проектирования есть много шаблонов, которые следуют принципу закрытости разработки, например: шаблон публикации-подписчика, шаблон метода шаблона, шаблон стратегии, шаблон прокси.
Иногда мы можем улучшить гибкость кода путем расширения и не можем удовлетворить все потребности сцены.Когда модификация неизбежна, разумно позволить пользователю изменить файл конфигурации для достижения индивидуальных потребностей, добавив файлы конфигурации. Изменение конфигурации намного проще, чем изменение исходного кода.
После приведенного выше введения давайте рассмотрим несколько распространенных шаблонов проектирования в разработке внешнего интерфейса.
-
одноэлементный шаблон
单例模式顾名思义:保证一个类仅有一个实例, 并且对外暴露一个能够访问到它的访问点。
Суть реализации паттерна singleton заключается в обеспечении того, чтобы у класса был только один экземпляр, а это значит, что при создании объекта нам нужно определить, был ли экземпляр создан ранее, и если он был создан, вернуть ранее созданный экземпляр , в противном случае создайте новый.
var fn = function() { this.instance = null; }; fn.getInstance = function() { //写法1 if (!this.instance) { this.instance = new fn(); } return this.instance; //写法2 return this.instance || (this.instance = new fn()); }; var fnA = fn.getInstance(); var fnB = fn.getInstance(); console.log(fnA === fnB); //true
В повседневных бизнес-сценариях одноэлементный режим также довольно распространен: например, на странице есть только одно модальное окно, и каждый раз нужно открывать и закрывать одно и то же, вместо того, чтобы постоянно создавать новое. И для оптимизации производительности мы должны создать его, когда он нам нужен, вместо того, чтобы уже существовать в доме, когда страница инициализируется, этоЛенивый одноэлементный шаблон.
//假设我们需要点击某个按钮时就显示出模态框,那么我们可以像下面这么实现。 var createModal = (function(){ var modal = null; return function() { if (!modal) { modal = document.createElement('div'); //... modal.style.display = 'none'; document.getElementById('container').append(modal); } return modal; } })(); document.getElementById('showModal').click(function() { var modal = createModal(); modal.style.display = 'block'; });
В приведенном выше коде мы поместили логику создания объектов и управления экземплярами в одно место, что нарушает принцип единой ответственности.Мы должны создать новый метод создания синглтона, чтобы мы могли не только создать уникальный модальный экземпляр, но также Может создавать других, с разделением ответственности.
var createSingleInstance = function(fn) { var instance = null; return function() { if (!instance) { instance = fn.apply(this, arguments); } return instance; } }; var createModal = function() { var modal = docuemnt.createElement('div'); //... modal.style.display = 'none'; document.getElementById('container').append(modal); return modal; }; var modal = createSingleInstance(createModal);
-
Шаблон наблюдателя
定义了对象与其他对象之间的依赖关系, 当某个对象发生改变的时候,所有依赖到这个对象的地方都会被通知。
Подобно ko.compute в Knockout.js и вычисляемой функции в vue, на самом деле это практика этого паттерна. Суть реализации шаблона наблюдателя заключается в том, что нам нужна переменная для хранения всех зависимостей, функция прослушивания для добавления зависимостей к переменной и триггерная функция для запуска уведомлений.
var observal = { eventObj: {}, listen: function(key, fn) { this.eventObj[key] = this.eventObj[key] || []; this.eventObj[key].push(fn); }, trigger: function(key) { var eventList = this.eventObj[key]; if (!eventList || eventList.length < 1) { return; } var length = eventList.length; for (var i = 0; i < length; i++) { var event = eventList[i]; event.apply(this, arguments); } } }; //定义要监听的事件 observal.listen('command1', function() { console.log('黑夜给了我夜色的眼睛~'); }); observal.listen('command1', function() { console.log('我却用它寻找光明~'); }); observal.listen('command2', function() { console.log('一花一世界~'); }); observal.listen('command2', function() { console.log('一码一人生~'); }); //触发某个监听的事件 observal.trigger('command1');//黑夜给了我夜色的眼睛~ 我却用它寻找光明~ observal.trigger('command2');//一花一世界~ 一码一人生~
Используя шаблон наблюдателя (шаблон публикации-подписки), мы можем сделать код более гибким и надежным. Подписчикам не нужно знать, от какого издателя пришло сообщение, а издателю не нужно знать, каким подписчикам будет отправлено сообщение.
Точно так же мы можем создать общедоступную библиотеку функций, в которой хранятся методы инструмента для создания наблюдения.Мы используем этот метод для создания объекта публикации-подписки, где нам нужно его использовать.
-
Другие шаблоны проектирования и принципы проектирования
Существует множество шаблонов проектирования, и я не буду их здесь раскрывать из-за ограниченного места. В 1995 году GoF предложила 23 шаблона проектирования. Например, проверка формы оптимизации в режиме стратегии, режим прокси, комбинированный режим, режим декоратора, режим адаптера... Их можно кратко обсудить позже, или вы сможете понять их позже сами. Общие шаблоны проектирования и принципы проектирования могут относиться к следующей карте ума.
После прочтения приведенной выше статьи я считаю, что у всех есть интуитивное понимание преимуществ шаблонов проектирования, а также общее представление о шаблоне singleton и шаблоне наблюдателя.
Шаблоны проектирования — это отличные организационные методы, которые были обобщены в большом количестве кодов и программных практик. У каждого шаблона проектирования есть свои сценарии адаптации, а в некоторых сценариях также используется несколько шаблонов проектирования. Только понимая больше шаблонов проектирования и осваивая сценарии адаптации каждого шаблона проектирования, мы можем лучше его использовать.
Но ***преждевременная оптимизация не всегда хороша или не нужна***, иногда мы не можем оптимизировать в начале, а когда возникают такие проблемы, как путаница в организации кода и дополнительное расширение в определенном сценарии приложения, мы будем повторно - оптимизировать рефакторинг, чтобы предотвратить преждевременную оптимизацию, которая не является ненужной или просто усложняет код. Как и в случае с редукцией, при обмене данными между компонентом страницы и компонентом определенные данные должны быть получены в любом компоненте, а об изменении данных, вызванном определенным поведением в любом компоненте, необходимо уведомить все места, где они используется, то в это время вы можете использовать избыточность, некоторые простые страницы форм или страницы отображения могут быть полностью без избыточности.
Тут не просто посмотреть, и напоследок расскажу вам анекдот, чтобы расслабиться:
从前有只麋鹿,它在森林里玩儿,不小心走丢了。
于是它给它的好朋友长颈鹿打电话:“喂…我迷路辣。”
长颈鹿听见了回答说:“喂~我长颈鹿辣~”
Ссылка: Цзэн Тан "Шаблоны проектирования и практика разработки JavaScript"
Официальный сайт iKcamp:www.ikcamp.com
Посетите официальный веб-сайт, чтобы быстрее ознакомиться со всеми бесплатными курсами обмена: «Продюсер IKcamp | Последние онлайн-программы WeChat Mini | Обмен учебными курсами для начинающих и среднего уровня на основе инструментов разработчика последней версии 1.0». Содержит: статьи, видео, исходный код
Оригинальная новая книга iKcamp «Эффективная разработка мобильного веб-интерфейса» была выпущена на Amazon, JD.com и Dangdang.
iKcamp последние события
Адрес регистрации:woohoo.events.com/event/54099…
а также
“天天练口语”
Команда R&D заняла четвертое место в общем списке мини-программ и первое место в категории образования при личном общении.
В 2019 году оригинальная новая книга iKcamp «Практика разработки Koa и Node.js» была продана на JD.com, Tmall, Amazon и Dangdang!