Что такое шаблоны проектирования?
Шаблоны проектирования используются в процессе проектирования и разработки программного обеспечения.Общее решение повторяющейся проблемы определенного типа. Шаблоны проектирования — это скорее направляющая идеология и методология, чем готовый код, и, конечно, каждый шаблон проектирования имеет конкретную реализацию на каждом языке. Изучение паттернов проектирования — это скорее понимание внутренних идей различных паттернов и решение проблем, ведь это лучшая практика, подытоженная бесчисленным опытом предшественников, а реализация кода — помощь в углублении понимания. Шаблоны проектирования используются дляПовторно используемый код, облегчающий понимание кода другими и обеспечивающий надежность кода.В этой статье я представлю пять из этих распространенных шаблонов проектирования на практике в JavaScript:
Дизайн Singleton Design
определение
Шаблон singleton позволяет классу или объекту иметь только один экземпляр и использует глобальную переменную для хранения этого экземпляра.
- РеализацияЯвляется ли судить, существует ли экземпляр объекта, если он уже существует, он не будет создан снова
- сцены, которые будут использоватьсяПрименимо только к одному экземпляру в бизнес-сценариях, таких как всплывающие окна, корзины покупок
выполнить
Синглтон в ленивый мужчина и голодал формулу:
- ленивый
let ShopCar = (function () {
let instance;
function init() {
/*这里定义单例代码*/
return {
buy(good) {
this.goods.push(good);
},
goods: [],
};
}
return {
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
},
};
})();
let car1 = ShopCar.getInstance();
let car2 = ShopCar.getInstance();
car1.buy('橘子');
car2.buy('苹果');
console.log(car1.goods); //[ '橘子', '苹果' ]
console.log(car1 === car2); // true
- голодный китаец
var ShopCar = (function () {
var instance = init();
function init() {
/*这里定义单例代码*/ return {
buy(good) {
this.goods.push(good);
},
goods: [],
};
}
return {
getInstance: function () {
return instance;
},
};
})();
let car1 = ShopCar.getInstance();
let car2 = ShopCar.getInstance();
car1.buy('橘子');
car2.buy('苹果'); //[ '橘子', '苹果' ]
console.log(car1.goods);
console.log(car1 === car2); // true
懒汉式
Когда класс загружается, экземпляр не создается, поэтому класс загружается быстро, но скорость получения объекта во время выполнения низкая;饿汉式
Инициализация выполняется при загрузке класса, поэтому загрузка класса происходит медленнее, но объект выполняется быстро.
режим стратегии
определение
Шаблон стратегии определяет серию алгоритмов, инкапсулирует каждый алгоритм и делает их взаимозаменяемыми.
- РеализацияОпределите набор переменных классов стратегии для инкапсуляции конкретных алгоритмов и определите набор неизменяемых классов среды для делегирования запросов определенному классу стратегии.
- сцены, которые будут использоватьсяОн подходит для бизнес-сценариев, в которых необходимо оценить несколько условий, и даже сложные условия вложены друг в друга.Шаблон стратегии можно использовать для улучшения удобства сопровождения и удобочитаемости кода. Например, оплата, проверка разрешения блога
выполнить
Пример:
// 定义几个策略类
var PaymentMethodStrategy = {
BankAccount: function (money) {
return money > 50 ? money * 0.7 : money;
},
CreditCard: function (money) {
return money * 0.8;
},
Alipay: function (money) {
return money;
},
};
/*环境类*/
var userPay = function (selectedStrategy, money) {
return PaymentMethodStrategy[selectedStrategy](money);
};
console.log('银行卡支付价格为:' + userPay('BankAccount', 100)); //70
console.log('支付宝支付价格为:' + userPay('Alipay', 100)); //100
console.log('信用卡支付价格为:' + userPay('CreditCard', 100)); //80
Шаблон наблюдателя
определение
Режим наблюдателя — это режим поведения объектов, который определяет отношение зависимости «один ко многим» между объектами, то есть отношение между несколькими наблюдателями и наблюдаемым объектом, при изменении наблюдаемого объекта он уведомляет все объекты Observer, которые выполняют соответствующие операции. .
- РеализацияДайте определение наблюдаемому объекту, наблюдателю. Уведомляет наблюдателя, когда состояние наблюдаемого объекта изменяется.
- сцены, которые будут использоватьсяПрименимо к бизнес-сценариям, когда состояние объекта изменяется, вам необходимо автоматически уведомлять другие связанные объекты, автоматически обновлять состояние объекта или выполнять метод соответствующего объекта.Например, когда вы учитель и вам нужно уведомить родителей в классе, вы можете создать группу (список). Каждый раз, когда вы уведомляете о событии, вам просто нужно прокрутить этот список (групповая отправка), и не важно, кто находится в этом списке.
выполнить
Пример:
// 创建一个群,保存通知,通知变化之后通知每个家长(触发所有观察者对象)
class Group {
constructor() {
this.message = '暂无通知';
this.parents = [];
}
getMessage() {
return this.message;
}
setMassage(message) {
this.message = message;
this.notifyAllObservers();
}
notifyAllObservers() {
this.parents.forEach((parent) => {
parent.update();
});
}
attach(parent) {
this.parents.push(parent);
}
}
// 观察者,每个家长
class Parent {
constructor(name, group) {
this.name = name;
this.group = group;
this.group.attach(this);
}
update() {
console.log(`${this.name} 收到通知: ${this.group.getMessage()}`);
}
}
let group = new Group();
let t1 = new Parent('李妈妈', group);
let t2 = new Parent('王爸爸', group);
let t3 = new Parent('张爷爷', group);
group.setMassage('开家长会');
group.setMassage('开运动会');
/*
李妈妈 收到通知: 开家长会
王爸爸 收到通知: 开家长会
张爷爷 收到通知: 开家长会
李妈妈 收到通知: 开运动会
王爸爸 收到通知: 开运动会
张爷爷 收到通知: 开运动会
*/
модель публикации-подписки
определение
Режим публикации-подписки означает, что объект, который хочет получать уведомления (Подписчик), подписывается на тему через настраиваемое событие, основанное на теме, а объект, который публикует событие (Издатель), уведомляет каждый объект-подписчик, который подписывается на тему, путем публикация тематического события.
выполнить
const pubSub = {
list:{},
subscribe(key,fn){ // 订阅
if (!this.list[key]) {
this.list[key] = [];
}
this.list[key].push(fn);
},
publish(){ // 发布
const arg = arguments;
const key = Array.prototype.shift.call(arg);
const fns = this.list[key];
if(!fns || fns.length<=0) return false;
for(var i=0,len=fns.length;i<len;i++){
fns[i].apply(this, arg);
}
},
unSubscribe(key) { // 取消订阅
delete this.list[key];
}
};
// 进行订阅
pubSub.subscribe('name', (name) => {
console.log('your name is ' + name);
});
pubSub.subscribe('sex', (sex) => {
console.log('your sex is ' + sex);
});
// 进行发布
pubSub.publish('name', 'ttsy1'); // your name is ttsy1
pubSub.publish('sex', 'male'); // your sex is male
Подписка на приведенный выше код основана на имени и темах пола для настройки события, публикация осуществляется через темы имени и пола, и передаются параметры пользовательского события, и, наконец, запускается пользовательское событие конкретной темы. .
Подписки на определенную тему можно отменить с помощью метода unSubscribe.
pubSub.subscribe('name', (name) => {
console.log('your name is ' + name);
});
pubSub.subscribe('sex', (sex) => {
console.log('your sex is ' + sex);
});
pubSub.unSubscribe('name');
pubSub.publish('name', 'ttsy1'); // 这个主题被取消订阅了
pubSub.publish('sex', 'male'); // your sex is male
Шаблон наблюдателя против шаблона публикации-подписки:
И шаблон наблюдателя, и шаблон публикации-подписки определяют зависимость «один ко многим», и при изменении соответствующего состояния выполняется соответствующее обновление.
Разница заключается в том, что в режиме наблюдателя ряд объектов Observer, которые зависят от объекта Subject, могут выполнять один и тот же конкретный метод обновления только после получения уведомления, а в режиме публикации-подписки вы можете выполнять различные настройки на основе разных тем. мероприятие.
Условно говоря, режим публикации-подписки более гибкий и изменчивый, чем режим наблюдателя.
Шаблон декоратора
определение
На основе неизменения исходной структуры и функции динамически украшать некоторые методы или свойства, подходящие для особых сценариев, то есть добавлять новые функции для расширения его определенных возможностей.
- РеализацияСоздан класс декоратора, чтобы обернуть исходный класс
- сцены, которые будут использоватьсяИсходный метод остается неизменным, а другие методы монтируются на исходный метод для удовлетворения существующих требований; развязка функций, функция разбивается на несколько повторно используемых функций, а затем разделенные функции монтируются на функцию, достигая того же эффект, но повысить возможность повторного использования. Такие как многодырочная розетка, модификация локомотива
выполнить
Пример:
const Man = function () {
this.run = function () {
console.log('跑步');
};
};
const Decorator = function (old) {
this.oldAbility = old.run;
this.fly = function () {
console.log('具备飞行能力');
};
this.newAbility = function () {
this.oldAbility();
this.fly();
};
};
const man = new Man();
const superMan = new Decorator(man);
superMan.newAbility(); //跑步 具备飞行能力
прокси-режим
определение
Режим прокси предоставляет прокси-объект для объекта, а прокси-объект управляет ссылкой на исходный объект. С точки зрения непрофессионала, агентская модель является обычным посредником в нашей жизни.
- РеализацияОпределите делегатора и агента, и действия, которые необходимо делегировать, выполняются в агенте.
- сцены, которые будут использоватьсяВ некоторых случаях клиентский класс не хочет или не может напрямую ссылаться на объект делегата, а объект прокси-класса может действовать как посредник между клиентским классом и объектом делегата. Прокси может помочь клиенту отфильтровать некоторые запросы и отложить создание некоторых дорогостоящих объектов до тех пор, пока они действительно не понадобятся. Посредники при покупке автомобилей, агенты по закупкам и представители класса собирают домашние задания для учителей.
выполнить
Пример:
class Letter {
constructor(name) {
this.name = name;
}
}
// 暗恋人小明
let XiaoMing = {
name: '小明',
sendLetter(target) {
target.receiveLetter(this.name);
},
};
// 代理小华
let xiaoHua = {
receiveLetter(customer) {
// 当然要等小红好心情时才送情书,也在送情书也才创建情书
XiaoHong.listenGoodMood(() => {
XiaoHong.receiveLetter(new Letter(customer + '的情书'));
});
},
};
// 心仪对象小红
let XiaoHong = {
name: '小红',
receiveLetter(letter) {
console.log(this.name + '收到:' + letter.name);
},
listenGoodMood(fn) {
setTimeout(() => {
fn();
}, 1000);
},
};
XiaoMing.sendLetter(xiaoHua); //小红收到:小明的情书
Прокси — это прокси, предоставляемый ES6 специально в роли прокси.Object.defineProperty устарел в части адаптивных данных Vue 3.0, вместо него используется прокси.
var proxy = new Proxy(target, handler);
Теперь используйте прокси-сервер для имитации другой сцены: для защиты одноклассников представитель класса будет публиковать только оценки и оценки. Кандидаты, которые сомневаются в результате балла, новый счет имеет право обновлять результаты, чем предыдущие 10 баллов.
const scoreList = { wang: 90, li: 60, wu: 100 };
const yyProxy = new Proxy(scoreList, {
get: function (scoreList, name) {
if (scoreList[name] > 69) {
console.log('输出成绩');
return scoreList[name];
} else {
console.log('不及格的成绩无法公示');
}
},
set: function (scoreList, name, val) {
if (val - scoreList[name] > 10) {
console.log('修改成绩');
scoreList[name] = val;
} else {
console.log('无法修改成绩');
}
},
});
yyProxy['wang'] = 98; //无法修改成绩
yyProxy['li'] = 80; //修改成绩
Суммировать
Раньше я думал, что шаблоны проектирования — это сумасшедшие, далекие рекомендации по разработке программного обеспечения. Потом я узнал, что я использовал их! Некоторые из представленных мной шаблонов используются во многих приложениях. Но в конце концов, это всего лишь теории. Для разработчика использование зависит от того, упрощает ли оно реализацию и поддержку логики кода после использования.