Объясните шаблоны проектирования JavaScript в духе League of Legends (1)!

JavaScript
Объясните шаблоны проектирования JavaScript в духе League of Legends (1)!

Шаблон конструктора

Введение

В JavaScript конструкторы обычно считаются специальными конструкторами, используемыми для реализации экземпляров. Вызывая определенный конструктор с ключевым словом new, вы можете сообщить JavaScript, что хотите создать новый объект и что объявления членов нового объекта определены в конструкторе. Внутри конструктора ключевое слово this относится к вновь созданному объекту.

Как фанат старой лиги,Должен сделать это вручнуюШаблоны проектирования также могут быть интегрированы.

Теперь я собираюсь создать объект League of Legends, для которого потребуются карты, герои, солдаты, монстры и кнопка для запуска игры.

function LOL(maps, heros, soldier, monster) {
    this.maps = maps
    this.heros = heros
    this.soldier = soldier
    this.monster = monster
    this.start = function() {
        return '地图:' + this.maps + '\n对战英雄:' + this.heros.join() + '\n小兵类型:' + this.soldier + '\n野怪:' + this.monster + '\n'
    }
}


var game1 = new LOL('召唤师峡谷', ['影流之主', '诡术妖姬'], '超级兵', '红buff')
var game2 = new LOL('大乱斗', ['影流之主', '诡术妖姬'], '超级兵', '红buff')
console.log(game1.start())
console.log(game2.start())

Напишите такой код, каждая игра должна воссоздавать экземпляр League of Legends,

Используя конструктор таким образом, существует столько же методов запуска функции, сколько и игр.Если вы используете общий метод запуска, вы можете сэкономить много памяти.

function LOL(maps, heros, soldier, monster) {
    this.maps = maps
    this.heros = heros
    this.soldier = soldier
    this.monster = monster
}
LOL.prototype.start = function() {
	 	return '地图:' + this.maps + '\n对战英雄:' + this.heros.join() + '\n小兵类型:' + this.soldier + '\n野怪:' + this.monster + '\n'
}


var game1 = new LOL('召唤师峡谷', ['影流之主', '诡术妖姬'], '超级兵', '红buff')
var game2 = new LOL('大乱斗', ['影流之主', '诡术妖姬'], '超级兵', '红buff')

console.log(game1.start())
console.log(game2.start())

Если вы позволитеstartБыло бы хорошо, если бы метод стал общим для всех, так что ставьтеLOL.prototype.startПерепишите, чтобы все экземпляры LOL могли совместно использовать метод, который можно наследовать от цепочки прототипов.

Вышеупомянутый способ может сэкономить память,startФункции экземпляра можно использовать во всех экземплярах объектов LOL.

Существуют и другие способы создания объектов без использования новых

function LOL(maps, heros, soldier, monster) {
    this.maps = maps
    this.heros = heros
    this.soldier = soldier
    this.monster = monster
    this.start = function() {
        return '地图:' + this.maps + '\n对战英雄:' + this.heros.join() + '\n小兵类型:' + this.soldier + '\n野怪:' + this.monster + '\n'
    }
}


var game3 = new Object();
LOL.call(game3, "扭曲丛林", ['影流之主', '剑圣'], '远程兵', '大龙');
console.log(game3.start())

//也可以不使用new ,通过call方法在game3的作用域调用LOL

Хотя этот метод может создать новый конструктор, он не может наследовать функцию прототипа LOL.

Если вы запустите функцию LOL() напрямую (без использования new), так как это указывает на объект окна, метод запуска станетwindow.start()

Если вы заставляете функцию использовать новый метод, вы также можете создать его следующим образом:

function LOL(maps, heros, soldier, monster) {
    if (!(this instanceof LOL)) {
        return new LOL(maps, heros, soldier, monster);
    }
    this.maps = maps
    this.heros = heros
    this.soldier = soldier
    this.monster = monster
}

Судя по этомуinstanceof, вы можете знать, что это происходит отnewметод или прямой вызов. Если он вызывается напрямую, условие оценкиtrue, все равно вернет новый экземпляр.

e.g:

var s = new String("lol");
var n = new Number(101);
var b = new Boolean(true);
// s n b返回的是实例对象 
//String{
//	0: 'l',
//	1: 'o',
//	2: 'l'
//	}

//可以直接给变量赋值,或者不加new 关键词

Внешний вид Режим

Введение

Самым большим воплощением режима появления на самом деле является вход, напримерinit()функцию, поместите некоторые внутренние функции под этот фасад, просто вызовите эту функцию фасада, и другие беспорядочные функции могут быть реализованы.

Теперь есть герой по имени Ясуо, я хочу дать ему какую-то конфигурацию, например навыки, одежду и т.д.

function YaSuo() {
}
function Qskill (hero) {
    hero.prototype.Qskill = function() {
        console.log('hasaki!!')
    }
}
function Wskill (hero) {
    hero.prototype.Wskill = function() {
        console.log('风墙')
    }
}
function Eskill (hero) {
    hero.prototype.Eskill = function() {
        console.log('快乐')
    }
}
function Rskill (hero) {
    hero.prototype.Rskill = function() {
        console.log('痛里唉该痛')
    }
}
function Skin (hero, skin) {
    hero.prototype.skin = skin
}

function CreateYasuo () {
    Qskill(YaSuo)
    Wskill(YaSuo)
    Eskill(YaSuo)
    Rskill(YaSuo)
    Skin(YaSuo, 'originSkin')
    return new YaSuo()
}
CreateYasuo()
// 创建成功 外观模式启动

С помощью приведенного выше кода был успешно создан красивый Yasuo. В конце концов, нам просто нужно понять,Паттерн Facade не только упрощает интерфейс в классе, но и отделяет интерфейс от вызывающей стороны. Фасадный режим часто считается обязательным для разработчиков, он может инкапсулировать некоторые сложные операции и создать простой интерфейс для вызова.

Грубо говоря, это использование интерфейса для инкапсуляции других интерфейсов.

Преимущество режима появления в том, что им легко пользоваться. Недостатком является то, что могут быть проблемы с производительностью, когда интерфейсы, созданные шаблоном Facade, используются постоянно.

e.g.

var addMyEvent = function (el, ev, fn) {
    if (el.addEventListener) {
        el.addEventListener(ev, fn, false);
    } else if (el.attachEvent) {
        el.attachEvent('on' + ev, fn);
    } else {
        el['on' + ev] = fn;
    }
}; 

Это наиболее распространенная обработка событий прослушивания, и внешний интерфейс должен знать об этом. один из нихaddMyEventЭто инкапсуляция трех других интерфейсов, которая создает фасад, который является режимом внешнего вида.

прокси-режим

Введение

На самом деле модель агентства во многом соприкасается с нашей жизнью. Например в es6proxyобъектов, а также VPN, которую мы обычно используем для серфинга в Интернете. Фактически, режим прокси позволяет объекту помогать другим объектам делать что-либо.

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

// 声明走路动作
function Walk (hero) { // 代理期间执行的操作
    return function() {console.log(hero + ' is walk')}
}
function Kalisita () { // proxy
    this.walk = Walk('Kalisita')
    this.Rskill = function(hero) { // 传入要拉取的英雄
        this.walk = function() {
            Walk('Kalisita')() // 既需要自己走
            hero.walk() // 还需要带着人一起走
        }
    }
}
function HeroA () { // 被代理走路的英雄
    this.walk = Walk('heroA')
}

var k = new Kalisita()
var a = new HeroA()

k.walk() // Kalisita is walk
a.walk() // heroA is walk

k.Rskill(a) // k把a的walk事件代理了, 现在k触发walk的同时,也会带着a一起walk哦
k.walk()
// Kalisita is walk 
// heroA is walk

Режим прокси в основном используется для нескольких точек,

  • Чтобы получить разрешение на работу с несуществующими объектами
  • Для получения удаленных файлов в качестве трамплина требуется режим прокси.
  • Создавайте дорогостоящие объекты по мере необходимости и используйте его для хранения реальных объектов, создание экземпляров которых занимает много времени.Например, при рендеринге браузера сначала отображается проблема, а картинка может отображаться медленно (то есть реальная картинка заменяется виртуальным прокси. , виртуальный агент сохраняет путь и размер реального образа.
  • Прокси делает что-то еще только при вызове реального объекта. Например, при сборке мусора в C# при использовании объекта будет несколько ссылок.Если на объект нет ссылок, сборщик мусора может его переработать.

详情可以参考《大话设计模式》

И больше, чем должен быть наш интерфейсный код.vue.jsОтзывчивый прокси для данных в данных.vue3также будет использовать многоES6支持的Proxy对象переписать.

e.g.

Через прокси попробуйте установить приватную собственность

function getPrivateProps(obj, filterFunc) {
  return new Proxy(obj, {
    get(obj, prop) {
      if (!filterFunc(prop)) {
        let value = Reflect.get(obj, prop);
        // 如果是方法, 将this指向修改原对象
        if (typeof value === 'function') {
          value = value.bind(obj);
        }
        return value;
      }
    },
    set(obj, prop, value) {
      if (filterFunc(prop)) {
        throw new TypeError(`Cant set property ${prop}`);
      }
      return Reflect.set(obj, prop, value);
    },
    has(obj, prop) {
      return filterFunc(prop) ? false : Reflect.has(obj, prop);
    },
    ownKeys(obj) {
      return Reflect.ownKeys(obj).filter(prop => !filterFunc(prop));
    },
    getOwnPropertyDescriptor(obj, prop) {
      return filterFunc(prop) ? undefined : Reflect.getOwnPropertyDescriptor(obj, prop);
    }
  });
}

function propFilter(prop) {
  return prop.indexOf('_') === 0;
}

Суммировать

Это вторая публикация автором шаблонов проектирования. Вы можете обратиться к предыдущей статье:

Запишите несколько шаблонов проектирования JavaScript (шаблон фабрики, шаблон синглтона, шаблон адаптера, шаблон декоратора, шаблон строителя).

На этот раз используются три общих шаблона проектирования, а именно шаблон конструктора, шаблон внешнего вида и шаблон прокси; все они являются распространенными шаблонами проектирования в повседневной разработке.

вes6proxyВы можете посетить блог учителя Руана, чтобы просмотреть подробный API, а также изучить исходный код vue для конкретного использования. Хотя прокси-режим очень полезен, его не рекомендуется использовать постоянно.Если вашему коду необходимо получить разрешения на определенные объекты, вы можете использовать прокси-режим. В более простых сценариях это может не понадобиться.

Режим внешнего вида используется чаще всего, в конце концов, каждому файлу js всегда нужна запись. Будь тоmainфункция илиinitВсе функции играют роль оболочки внешнего вида. Конечно, режим внешнего вида не обязательно должен существовать как запись в файле, если можно извлечь повторяющийся код, это разумный режим внешнего вида.

Нечего сказать о шаблоне конструктора, он прост и удобен в использовании.

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

  • Сведите к минимуму операции ввода-вывода, такие как операции с базой данных, отправка по сети и даже printf, которые во много раз медленнее, чем прямые операции с памятью.

  • При изменении ошибки вы должны начать с самого простого и основного места для проверки, не проверяя, что нижний слой в порядке, и обнаружить, что определенный переданный параметр неверен. Не сомневайтесь пока в частях системы.

  • Проектируйте архитектуру и в то же время разбирайтесь в деталях.Некоторые ошибки могут быть трудоемкими и трудоемкими для корректировки, и даже занять два или три дня.На самом деле, когда я написал это в то время, пока я заплатил немного внимание, этого можно было бы легко избежать. Затраты на предотвращение ошибок далеки от затрат на их поиск и исправление.

  • Разделите длинный кусок кода на множество маленьких функций, которые легко поддерживать.Даже код, который вы не хотите читать или изменять, на 100% проблематичен.

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

  • Когда новые функции, структура данных проекта, на более важной позиции

Я надеюсь, что этот обмен будет интересным и полезным для вас, спасибо за чтение.

Ссылаться на

Блог дяди Тома