Те шаблоны проектирования, которые вы используете непреднамеренно (1) - шаблоны создания

Шаблоны проектирования JavaScript
Те шаблоны проектирования, которые вы используете непреднамеренно (1) - шаблоны создания

предисловие

Несколько дней назад я поделился несколькими менее строгими интеллект-картами, в том числе одной о шаблонах проектирования:

Давно помню только несколько паттернов проектирования, и они плохо применяются.

Мы просто используем эту диаграмму как набросок и говорим о тех шаблонах проектирования, которые мы используем непреднамеренно — творчески.

1. Три заводских режима:Factory Pattern

Вообще говоря, три шаблона проектирования:

  • Простой заводской шаблон (Simple Factory)
  • Шаблон фабричного метода (Factory method)
  • Абстрактный заводской узор (Abstract factory)

Его ядро:

Роль фабрики заключается в том, чтобы скрыть сложность создания экземпляра, а нужно только предоставить простой и понятный интерфейс. --- Отрывок из книги «Путь фронтенд-интервью»

Разница в следующем:

  • Простой фабричный шаблон, используемый для создания экземпляра определенного объекта продукта, используемый для создания одного объекта.
  • Шаблон фабричного метода откладывает создание экземпляра до подклассов.
  • Шаблон абстрактной фабрики — это фабричная абстракция класса, используемого для создания кластера класса продукта, и он не отвечает за создание экземпляра продукта определенного типа.

На самом деле из того, что вы бы использовалиjQueryС самого начала уже используется заводской шаблон:

Шаблоны проектирования JavaScript и практика — Factory Pattern

1. jQueryиз$(selector)

jQueryсередина$('div')а такжеnew $('div')Какой лучше использовать? явно прямой$()наиболее удобно, потому что$()Это уже заводской метод.

class jQuery {
    constructor(selector) {
        super(selector)
    }
    //  ....
}

window.$ = function(selector) {
    return new jQuery(selector)
}

2. ReactизcreateElement()

React.createElement()метод является фабричным методом

  React.createElement('h1', null, 'Hello World!'),

3. VueАсинхронный компонент

пройти черезpromiseПутьresolveиз компонента

Соответствующий исходный код:

export function createComponent (
  Ctor: Class<Component> | Function | Object | void,
  data: ?VNodeData,
  context: Component,
  children: ?Array<VNode>,
  tag?: string
): VNode | Array<VNode> | void {
    // ...逻辑处理
    // async component
    let asyncFactory
    const vnode = new VNode(
    `vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
    data, undefined, undefined, undefined, context,
    { Ctor, propsData, listeners, tag, children },
    asyncFactory
    )
}

2. Одноэлементный шаблон:Singleton Pattern

Шаблон Singleton — один из самых простых шаблонов проектирования. Объяснить на просторечии это:

Экземпляры доступны везде

Есть три основных момента шаблона singleton:

  • Класс может иметь только один экземпляр;
  • Он должен сам создать этот экземпляр;
  • Он должен предоставить этот экземпляр для всей системы сам по себе.

С конкретной точки зрения реализации это следующие три момента:

  • Класс одноэлементного шаблона предоставляет только частный конструктор
  • Определение класса содержит статический частный объект класса
  • Этот класс предоставляет статическую общедоступную функцию для создания или получения собственного статического закрытого объекта.

Точно так же это также один из самых ранних шаблонов проектирования, с которыми мы столкнулись:

1. Ссылка на сторонние библиотеки

Несколько ссылок будут использовать только одну ссылку на библиотеку, напримерjQuery,lodash,momentЖдать.

2. Vuex / Redux

глобальное управление состояниемstore

Vuexа такжеReduxДанные хранятся в одномstoreсередина,MobxХранить данные в распределенномstoreсередина

const store = createStore(reducer)

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

3. VueУстановка сторонних плагинов в

ПервыйVuexУстановить:

let Vue // bind on install

export function install (_Vue) {
  if (Vue && _Vue === Vue) {
    // 如果发现 Vue 有值,就不重新创建实例了
    return
  }
  Vue = _Vue
  applyMixin(Vue)
}

Другие аналогичны, если вам интересно, вы можете перейти кGitHubпоискexport function install (Vue)

4. Простая реализация одноэлементного паттерна:

class SingletonClass {
  constructor() {
    if (!SingletonClass.instance) {
      SingletonClass.instance = this;
    }

    return SingletonClass.instance;
  }
  // other things
}

const instance = new SingletonClass();
Object.freeze(instance);

export default instance;

3. Режим строителя:Builder Pattern

, режим строителя в основном используется для«Построение сложного объекта шаг за шагом»

Здесь «шаг за шагом» является стабильным алгоритмом, а части сложных объектов часто меняются.

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

Скевоморфная интерпретация концепции режима строителя

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

1. jQueryстроитель в

jQueryРежим среднего строителя отражается в:

$( "<div class= "foo">bar</div>" );

$( "<p id="test">foo <em>bar</em></p>").appendTo("body" );

var newParagraph = $( "<p />" ).text( "Hello world" );

$( "<input />" )
      .attr({ "type": "text", "id":"sample"});
      .appendTo("#container");

НижеjQueryВнутри исходного кодаjQuery.prototypeФрагмент метода, который будет передан от кjQuery()Конструкция тегов для селекторовjQueryобъект.

Неважно, еслиdocument.createElementДля создания новых элементов ссылки на элементы (найденные или созданные) вводятся в возвращаемый объект, поэтому.attr()Сразу же после этого можно использовать другие методы.

  // HANDLE: $(html) -> $(array)
    if ( match[1] ) {
      context = context instanceof jQuery ? context[0] : context;
      doc = ( context ? context.ownerDocument || context : document );
      
      //如果传入的是单个字符串,并且是单个标记
      //只需执行createElement并跳过其余部分
    
      ret = rsingleTag.exec( selector );

      if ( ret ) {
        if ( jQuery.isPlainObject( context ) ) {
          selector = [ document.createElement( ret[1] ) ];
          jQuery.fn.attr.call( selector, context, true );

        } else {
          selector = [ doc.createElement( ret[1] ) ];
        }

      } else {
        ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
        selector = ( ret.cacheable ? jQuery.clone(ret.fragment) 
        : ret.fragment ).childNodes;
      }

      return jQuery.merge( this, selector );

1. Идеальная реализация шаблона строителя

По сути, цель шаблона Builder — уменьшить количество параметров, используемых конструкторами, и предоставить способ добавления гибкого поведения к объектам.

// 使用建造者模式之前
const person1 = new Person('Peter', 26, true, 40074986, 4, 2);

// 使用建造者模式之后
const person1 = new Person();
person1
  .name('Peter')
  .age(26)
  .member(true)
  .phone(40074986)
  .children(4)
  .cars(2);

2. ES6режим строителя в

Предположим, что в бизнес-сценарии системы ввода товаров есть четыре обязательных данных, а именно: название, цена и классификация. Долженbuildметод вернет окончательныйJavaScriptобъект.

/书籍建造者类
class ProductBuilder {
  constructor() {
    this.name = '';
    this.price = 0;
    this.category = '';
  }

  withName(name) {
    this.name = name
    return this
  }

  withPrice(price) {
    this.price = price
    return this
  }

  withCategory(category) {
    this.category = category
    return this
  }

  build() {
    return {
      name: this.name,
      price: this.price,
      category: this.category,
    }
  }
}

console.log(
  new ProductBuilder()
    .withName('《哈利·波特》')
    .withCategory('book')
    .withPrice('29.9')
    .build()

Хотя объектов всего три, наш конструктор уже довольно большой и требует многоwithers.

Размер построителя растет линейно с количеством полей. у нас слишком многоwithxxxxметод. На самом деле мы можем автоматически создавать такого родаwithxxxxметод упрощения кода.

3. Упрощенный режим строителя

class ProductBuilder {
  constructor() {
    this.name = ''
    this.price = ''
    this.category = 'other'

    // 为每个属性生成`wither`
    Object.keys(this).forEach(key => {
      const witherName = `with${key.substring(0, 1).toUpperCase()}${key.substring(1)}`
      this[witherName] = value => {
        this[key] = value
        return this
      }
    })
  }

  build() {
    // 获取此生成器的所有非函数属性的数组
    const keysNoWithers = Object.keys(this).filter(key => typeof this[key] !== 'function')

    return keysNoWithers.reduce((returnValue, key) => {
      return {
        ...returnValue,
        [key]: this[key],
      }
    }, {})
  }
}

console.log(
  new ProductBuilder()
    .withName('《哈利波特》')
    .withCategory('book')
    .build()
)

Мы автоматически создадим все методы построения с xxxx при вызове конструктора Здесь мы используем новый синтаксис ES6: Object.keys получает массив свойств объекта, ... синтаксис для слияния объектов

В итоге у нас есть декларативный (легкий для понимания) подход и шаблон построителя, в котором свойства можно добавлять динамически.

5. Извлеките общие части и внедрите несколько сборщиков

Когда у вас много построителей, мы можем легко извлечь их обобщенные части в общий родительский класс, что упрощает создание новых построителей.

class BaseBuilder {
  init() {
    Object.keys(this).forEach((key) => {
      const witherName = `with${key.substring(0,1).toUpperCase()}${key.substring(1)}`;
      this[witherName] = (value) => {
        this[key] = value;
        return this;
      };
    });
  }

  build() {
    const keysNoWithers = Object.keys(this).filter((key) => (
      typeof this[key] !== 'function'
    ));

    return keysNoWithers.reduce((returnValue, key) => {
      return {
        ...returnValue,
        [key]: this[key]
      };
    }, {});
  }
}

Затем вы можете создать несколько сборщиков:

class ProductBuilder extends BaseBuilder {
  constructor() {
    super();

    this.name = '《前端劝退秘诀》';
    this.price = 9.99;
    this.category = 'other';

    super.init();
  }
}

Видно, что использование шаблона построителя подходит только для создания чрезвычайно сложных объектов. В реальном интерфейсном бизнесе, когда нет такого чрезвычайно сложного создания объектов, объекты должны создаваться непосредственно с использованием объектных литералов или фабричных шаблонов.

4. Режим прототипа

prototype...и тогда я буду зарублен насмерть.

5. Далее: Шаблоны структурного проектирования

Изначально я планировал ограничиться более чем 10 000 слов и снова и снова писать все шаблоны проектирования.

Но я думаю, что этот опыт чтения на самом деле не очень хорош (в основном лень, я хочу писать медленно.)

Ах да, теперь еще есть надежные инсайдеры, которые могут связаться со мной

  • WeChat:huab119
  • Почта:454274033@qq.com

Справочная статья

Сборник статей автора Nuggets

Если вам нужно перепечатать его в публичный аккаунт, просто позвоните мне и добавьте его в белый список.

Нет публики