Паттерн проектирования — это часто встречающееся решение определённой проблемы при проектировании архитектуры программ.
function Bob() {
this.prefix = '';
this.say = function() {
console.log(`${this.prefix}, i'm Bob`);
}
}
const person = new Bob();
person.prefix = 'Hello';
person.say();
function Piter() {
this.prefix = '';
this.say = function () {
console.log(`${this.prefix}, i'm Piter`);
}
}
const person = new Piter();
person.prefix = 'Hello';
person.say();
function Factory() {
this.create = function(type) {
this.person = null;
switch (type) {
case 'Bob':
this.person = new Bob();
break;
case 'Piter':
this.person = new Piter();
break;
default:
return this.person;
}
this.person.prefix = 'Hello';
return this.person;
};
}
const person = new Factory();
const bob = person.create('Bob');
bob.say();
const piter = person.create('Piter');
piter.say();
function Person(name) {
this.prefix = '';
this.say = function () {
console.log(`${this.prefix}, i'm ${name}`);
}
}
function PersonFactory() {
this.create = function (name, welcomeText) {
const person = new Person(name);
person.prefix = welcomeText;
return person;
};
}
const personFactory = new PersonFactory();
const bob = personFactory.create('Bob', 'Hello');
bob.say();
const piter = personFactory.create('Piter', 'Hello');
piter.say();
function TreeFactory() {
this.create = function (branchCount) {
const tree = new Tree();
tree.branchCount = branchCount;
return tree;
};
}
const treeFactory = new TreeFactory();
const oak = treeFactory.create(5);
Строитель — это порождающий паттерн проектирования, который позволяет создавать сложные объекты пошагово
function Plant() {
this.build = function(builder) {
builder.step1();
builder.step2();
builder.step3();
return builder.get();
}
}
function RobotBuilder() {
this.robot = null;
this.step1 = function() {
this.robot = new Robot();
}
this.step2 = function() {
this.robot.arm = 2;
}
this.get = function() {
return this.robot;
}
}
function Robot() {
this.say = function() {
console.log(`Hello, I'm robot with ${this.arm} arms`);
}
}
const director = new Plant();
const robot = director.build(new RobotBuilder);
const robot1 = director.build(new RobotBuilder);
robot.say();
robot1.say();
function Robot() {
this.name = '';
this.say = function() {
console.log(`Hello, I'm a Robot, my name is ${this.name}`);
}
}
const firstRobot = new Robot();
firstRobot.name = 'Chappy';
firstRobot.say();
function RobotCloneMaker(proto) {
this.proto = proto;
this.clone = function() {
const robot = new Robot();
robot.name = this.proto.name;
return robot;
}
}
const firstRobot = new Robot();
firstRobot.name = 'Chappy';
const cloneMaker = new RobotCloneMaker(firstRobot);
const secondRobot = cloneMaker.clone();
const thirdRobot = cloneMaker.clone();
secondRobot.say();
thirdRobot.say();
const simple = {
a: 1,
b: 2
};
const anotherSimple = simple;
console.log(anotherSimple, anotherSimple === simple);
function Singletone() {
if (this.__proto__.instance) return this.__proto__.instance;
this.name = 'Bob';
this.__proto__.instance = this;
return this.__proto__.instance;
}
const withProto = new Singletone();
const withProto1 = new Singletone();
console.log(withProto, withProto1, withProto === withProto1);
class SingletoneOne { // ES7
static instance;
constructor() {
if (instance) return instance;
this.instance = this;
}
}
const classProto1 = new SingletoneOne();
const classProto2 = new SingletoneOne();
console.log(classProto1, classProto1, classProto1 === classProto2);
function calculator(action, a, b) {
console.log(action.calc(a, b));
}
function Division() {
this.calc = function (a, b) {
return a / b;
};
}
const division = new Division();
function calculator(action, a, b) {
console.log(action.calc(a, b));
}
calculator(division, 6, 3);
function Substraction() {
this.first = null;
this.second = null;
this.setFirst = function(val) {
this.first = val;
}
this.setSecond = function (val) {
this.second = val;
}
this.calc = function () {
return this.first - this.second;
}
}
/* interface 1 */
XXX.calc(a, b);// -> result
/* interface 2 */
YYY.setFirst(a);
YYY.setSecond(b);
YYY.calc();// -> result
function SubstractionAdapter(substraction) {
this.calc = function(a, b) {
substraction.setFirst(a);
substraction.setSecond(b);
return substraction.calc();
}
}
Мост — это структурный паттерн проектирования, который разделяет один или несколько классов на две отдельные иерархии — абстракцию и реализацию, позволяя изменять их независимо друг от друга.
const cache = new Cache(store);cache.set({key: 111}, 'aaa');
cache.get('aaa');
cache.clear();
/** Abstraction */
function Store(implementation) {
this.setItem = function(key, value) {
implementation.setItem(key, value);
};
this.getItem = function(key) {
return implementation.getItem(key);
};
this.clear = function() {
implementation.clear();
};
}
/** Implementation */
function FileStorage() {
this.setItem = function (key, value) {
/** save to file*/
console.log('saved');
};
this.getItem = function (key) {
/** read from file*/
console.log('got');
};
this.clear = function () {
/** remove file*/
console.log('clear');
};
}
/** User code */
let store;
if(typeof window != 'undefined') {
store = new Store(localStorage);
} else {
const fileStorage = new FileStorage();
store = new Store(fileStorage);
}
const cache = new Cache(store);
cache.set({key: 111}, 'aaa');
cache.get('aaa');
cache.clear();
function User(name) {
this.name = name;
this.say = function() {
console.log(`Hello, I'm ${this.name}`);
}
}
const bob = new User('Bob');
bob.say();
function ExtendedUser(user, surname) {
this.user = user;
this.name = user.name;
this.surname = surname;
this.say = function () {
console.log(`Hello, I'm ${this.name} ${this.surname}`);
}
}
const Bob = new User('Bob');
const BobMarko = new ExtendedUser(Bob, 'Marko');
BobMarko.say();
function complicatedFunction1(value) {
console.log(`Do something very complicated with `);
return true;
}
function complicatedFunction2() {
console.log('Do something complicated');
}
function complicatedFunction3() {
console.log('Do something else');
}
function Facade(value) {
this.value = value;
this.doSomething = function() {
if (complicatedFunction1(value)) {
complicatedFunction2();
}
complicatedFunction3();
}
}
const doIt = new Facade('Some data');
doIt.doSomething();
function ConsoleProxy() {
this.log = function(message) {
console.log('======== BEFORE ========');
console.log(message);
console.log('======== AFTER ========');
}
}
const console2 = new ConsoleProxy();
console2.log('Hello');
<div>
<a href="/" >Link</a>
</div>
=========================
const el = new gQuery('div').find('a').addClass('active').getSelector();
console.log(el); // -> ???
function gQuery(selector) {
this.selector = selector;
this.find = function(el) {
console.log(`Do something to find ""`);
this.selector = el;
return this;
}
this.addClass = function (className) {
console.log(`Do something to add className ""`);
this.selector += `.`;
return this;
}
this.getSelector = function () {
return this.selector;
}
}
function add(a, b) {
return a + b;
}
function substract(a, b) {
return a - b;
}
function Command(action, undo, value) {
this.action = action;
this.undo = undo;
this.value = value;
}
Примерfunction AddCommand(value) {
return new Command(add, substract, value);
}
function Iterator(items) {
this.items = items;
this.index = 0;
}
Iterator.prototype = {
first: function() {
this.reset();
return this.items[this.index];
},
last: function () {
this.index = this.items.length - 1;
return this.items[this.index];
},
next: function() { return this.items[this.index++]; }
reset: function() { this.index = 0; },
hasNext: function() { return this.index < this.items.length; }
};
const iterator = new Iterator([1, 2, 3]);
while(iterator.hasNext()) {
console.log(iterator.next());
}
console.log(iterator.first());
console.log(iterator.last());
function Observer() {
this.handlers = [];
this.subscribe = function(fn) {
this.handlers.push(fn);
};
this.unsubscribe = function (fn) {
this.handlers = this.handlers.filter(item => item.toString() !== fn.toString());
};
this.trigger = function (data, context) {
this.handlers.map(fn => {
fn.call(context, data);
});
};
}
function Delivery() {
this.handler = null;
this.setStrategy = strategy => this.handler = strategy;
this.calculate = () => this.handler.calculate();
}
function NovaPoshta() {
this.calculate = () => 25;
}
function FedEx() {
this.calculate = () => 500;
}
const delivery = new Delivery();
delivery.setStrategy(new NovaPoshta());
console.log(delivery.calculate());
delivery.setStrategy(new FedEx());
console.log(delivery.calculate());
const arr = [1, 2, 3, 4, 5, 6];
function walk(a) {
a.map(el => console.log(el));
}
dirty();
walk(arr); // -> ???
function dirty() {
console.log('Do some action somewhere in your code and...');
arr[3] = 100;
}
Функциона́льное программи́рование — раздел дискретной математики и парадигма программирования, в которой процесс вычисления трактуется как вычисление значений функций в математическом понимании последних (в отличие от функций как подпрограмм в процедурном программировании).
ФП — это стиль написания программ, при котором просто комбинируется набор функций. В частности, ФП подразумевает обёртывание в функции практически всего подряд.
var increment = 0;
function autoIncrement() {
return ++increment;
}
var current = autoIncrement();
console.log(current); // -> ???
autoIncrement()
– не чистая функция
counter
counter
var increment = 0;
function autoIncrement(value) { // Чистая функция
return ++value;
}
var current = autoIncrement(increment);
console.log(current); // -> ???
В результате вычисления ссылочно прозрачной функции она дает одно и то же значение для одних и тех же аргументов. Такие функции называются чистыми функциями.
или ссылочно прозрачные
Функция является чистой если:
возможность зафиксировать часть аргументов многоместной функции и создать другую функцию, меньшей арности
Арность – количество аргументов функции
function add(a, b) {
return a + b;
}
function addPartial(value) {
return function(b) { return add(value, b)}
}
const add5to = addPartial(5); // -> ???
function add(a, b) {
return a + b;
}
function addPartial(value) {
return function(b) { return add(value, b)}
}
const add5to = addPartial(5); // -> ???
console.log(add5to(3)); // -> ???
console.log(addPartial(5)(3)); // -> ???
function volume(width, height, length) {
return width * height * length;
}
console.log(volume(2, 3, 100));
function volumeByLength(length) {
return function (width, height) { return volume(width, height, length) }
}
const volumeByLength100 = volumeByLength(100);
console.log(volumeByLength100(2,3));
Объектами первого класса в контексте конкретного языка программирования называются элементы, которые могут быть переданы как параметр, возвращены из функции, присвоены переменной
const fn = function() {
//
}
const someObject = {
method: function() { //... }
}
fn(someObject.method);
Функция высшего порядка — в программировании функция, принимающая в качестве аргументов другие функции или возвращающая другую функцию в качестве результата. Основная идея состоит в том, что функции имеют тот же статус, что и другие объекты данных.
function addPartial(value) {
return function(b) { return add(value, b)}
}
function calc(action, a, b) { return action(a, b); }
Мемоизация — сохранение результатов выполнения функций для предотвращения повторных вычислений
function add(a, b) {
var i = 0;
while(i < 10000000000) {
i++;
}
return a + b;
}
function memoization(fn) {
const cache = {};
return function(...args) {
const hash = args.join('-'); // ???
if (cache[hash]) {
console.log('Get data from cache');
return cache[hash];
}
console.log('Calculate data');
cache[hash] = fn(...args);
return cache[hash];
}
}
Denis Zavgorodny
|