5 шаблонов проектирования, которые вы должны знать о веб-разработке

JavaScript
5 шаблонов проектирования, которые вы должны знать о веб-разработке

Что такое шаблоны проектирования?

Шаблоны проектирования используются в процессе проектирования и разработки программного обеспечения.Общее решение повторяющейся проблемы определенного типа. Шаблоны проектирования — это скорее направляющая идеология и методология, чем готовый код, и, конечно, каждый шаблон проектирования имеет конкретную реализацию на каждом языке. Изучение паттернов проектирования — это скорее понимание внутренних идей различных паттернов и решение проблем, ведь это лучшая практика, подытоженная бесчисленным опытом предшественников, а реализация кода — помощь в углублении понимания. Шаблоны проектирования используются дляПовторно используемый код, облегчающий понимание кода другими и обеспечивающий надежность кода.В этой статье я представлю пять из этих распространенных шаблонов проектирования на практике в 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; //修改成绩

Суммировать

Раньше я думал, что шаблоны проектирования — это сумасшедшие, далекие рекомендации по разработке программного обеспечения. Потом я узнал, что я использовал их! Некоторые из представленных мной шаблонов используются во многих приложениях. Но в конце концов, это всего лишь теории. Для разработчика использование зависит от того, упрощает ли оно реализацию и поддержку логики кода после использования.