diff --git a/src/patterns/01-abstractFactory/example.js b/src/patterns/01-abstractFactory/example.js
deleted file mode 100644
index b706559..0000000
--- a/src/patterns/01-abstractFactory/example.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-ComponentFactory
-createButton
-createInput
-createTable
-*/
-
-interface ComponentFactory {
- createButton(): Button;
- createInput(): Input;
- createTable(): Table;
-}
-
-const darkThemeFabric = {
- getButton() {
- return Button
- },
- createInput() {
- return
- },
- createTable() {
- return
}
-}
-const defaultThemeFabric = {
- createButton() {
-
- },
- createInput() {
-
- },
- createTable() {}
-}
-const nativeThemeFabric = {
- createButton() {
-
- },
- createInput() {
-
- },
- createTable() {}
-}
-
-
-function createButton(fabric: ComponentFactory) {
- return fabric.createButton();
-}
-
-function createInput(fabric: ComponentFactory) {
-
-}
-
-function createTable(fabric: ComponentFactory) {
-
-}
-
-function App() {
- return {...}
-}
-
-
-function Component() {
- const fabric = useContext(FabricContext)
- return
- {currentFabric.createButton()}
-
-}
\ No newline at end of file
diff --git a/src/patterns/01-abstractFactory/index.js b/src/patterns/01-abstractFactory/index.js
index 6747591..b110f18 100644
--- a/src/patterns/01-abstractFactory/index.js
+++ b/src/patterns/01-abstractFactory/index.js
@@ -1,22 +1,50 @@
-export class SuccessButton {}
-export class ErrorButton {}
-export class SuccessNotification {}
-export class ErrorNotification {}
+export class SuccessButton {
+ create() {
+ return 'Button
'
+ }
+}
+
+export class ErrorButton {
+ create() {
+ return 'Button
'
+ }
+}
+
+export class SuccessNotification {
+ create() {
+ return 'Notification
'
+ }
+}
+
+export class ErrorNotification {
+ create() {
+ return 'Notification
'
+ }
+}
export class SuccessControl {
create (type = '') {
- // todo: implement logic
+ if (type === 'notification')
+ return new SuccessNotification()
+ else
+ return new SuccessButton()
}
}
export class ErrorControl {
create (type = '') {
- // todo: implement logic
+ if (type === 'notification')
+ return new ErrorNotification()
+ else
+ return new ErrorButton()
}
}
export default class ControlsFactory {
getFactory (factoryType = '') {
- // todo: implement logic
+ if (factoryType === 'error')
+ return new ErrorControl()
+ else
+ return new SuccessControl()
}
}
diff --git a/src/patterns/02-builder/example.js b/src/patterns/02-builder/example.js
deleted file mode 100644
index 4de17e0..0000000
--- a/src/patterns/02-builder/example.js
+++ /dev/null
@@ -1,29 +0,0 @@
-const playerConfig = {
- config: {},
-
- addAdConfig() {
-
- },
-
- addDrmConfig({url, type}) {
- this.config.drmUrl = url;
- this.config.drmType = type;
- },
-
- addTrackerConfig() {
-
- },
-
- addDeviceConfig() {
-
- },
-}
-
-
-const config = new PlayerConfig('theBestFilmUrl');
-
-if (isDrmNeeded) {
- config.addDrmConfig({type: 'widevine', url: ''});
-}
-
-
diff --git a/src/patterns/02-builder/index.js b/src/patterns/02-builder/index.js
index 8d7f02c..7ad53d1 100644
--- a/src/patterns/02-builder/index.js
+++ b/src/patterns/02-builder/index.js
@@ -1,17 +1,21 @@
export default class RequestBuilder {
constructor(url = '') {
- this.url = new URL(url);
+ this.url = new URL(url)
}
addPagination (start, end) {
- // todo: implement logic
+ this.url.searchParams.set('start', start)
+ this.url.searchParams.set('end', end)
}
addSort (sort, order) {
- // todo: implement logic
+ this.url.searchParams.set('sort', sort)
+ this.url.searchParams.set('order', order)
}
addFilter (filter, filterLte, filterGte) {
- // todo: implement logic
+ this.url.searchParams.set('filter', filter)
+ this.url.searchParams.set('filter_lte', filterLte)
+ this.url.searchParams.set('filter_gte', filterGte)
}
}
diff --git a/src/patterns/03-factoryMethod/example.js b/src/patterns/03-factoryMethod/example.js
deleted file mode 100644
index 644912e..0000000
--- a/src/patterns/03-factoryMethod/example.js
+++ /dev/null
@@ -1,37 +0,0 @@
-
-class FabricNode {
- draw() {
- return
- }
-}
-
-class StorageNode {
- draw() {
- return
- }
-}
-
-const config = {
- fabric: {
-
- },
- storage: {
-
- },
- region: {
- fabric: {},
- storage: {},
- town: {
- fabric: {},
- storage: {},
- }
- }
-}
-
-
-function paint(node) {
- const view = node.draw();
-
-
-}
-
diff --git a/src/patterns/03-factoryMethod/index.js b/src/patterns/03-factoryMethod/index.js
index a299f29..0e561d7 100644
--- a/src/patterns/03-factoryMethod/index.js
+++ b/src/patterns/03-factoryMethod/index.js
@@ -2,22 +2,36 @@ class Input {
element = {};
create () {
- // Abstract method
+ return this.element
}
}
export class TextInput extends Input {
- // todo: implement logic
+ create() {
+ this.element.type = 'text'
+ super.create()
+ }
}
export class NumberInput extends Input {
- // todo: implement logic
+ create() {
+ this.element.type = 'number'
+ super.create()
+ }
}
export class EmailInput extends Input {
- // todo: implement logic
+ create() {
+ this.element.type = 'email'
+ super.create()
+ }
}
export const inputFactory = (type = '') => {
- // todo: implement logic
+ if (type === 'number')
+ return new NumberInput()
+ else if (type === 'email')
+ return new EmailInput()
+
+ return new TextInput()
};
diff --git a/src/patterns/04-prototype/examples.js b/src/patterns/04-prototype/examples.js
deleted file mode 100644
index 662a254..0000000
--- a/src/patterns/04-prototype/examples.js
+++ /dev/null
@@ -1,20 +0,0 @@
-const storageNode = {
- id: 'asdasdasdas',
- level: 100,
- quality: {
- a: 1,
- b: 2,
- c: 3,
- },
-
-
- clone() {
- return {
- ...storageNode,
- quality: {
-
- },
- id: nanoid(),
- }
- }
-}
\ No newline at end of file
diff --git a/src/patterns/04-prototype/index.js b/src/patterns/04-prototype/index.js
index 208269d..eab870d 100644
--- a/src/patterns/04-prototype/index.js
+++ b/src/patterns/04-prototype/index.js
@@ -1,20 +1,27 @@
class Monster {
- // todo: implement logic
+ constructor(settings = {}) {
+ this.settings = settings
+ }
}
export default class Location {
- monsters = [];
+ monsters = []
constructor(name = '', monstersCount = 0, monstersSettings = {}) {
- this.name = name;
- // todo: implement logic
+ this.name = name
+ this.monstersCount = monstersCount
+ this.monstersSettings = monstersSettings
+
+ this.initMonsters()
}
initMonsters () {
- // todo: implement logic
+ for (let i = 0; i < this.monstersCount; i++) {
+ this.monsters.push(new Monster(this.monstersSettings));
+ }
}
clone () {
- // todo: implement logic
+ return { ...new Location() }
}
}
diff --git a/src/patterns/05-singleton/example.js b/src/patterns/05-singleton/example.js
deleted file mode 100644
index 2630fb9..0000000
--- a/src/patterns/05-singleton/example.js
+++ /dev/null
@@ -1,19 +0,0 @@
-const player = {
- play() {}
-}
-
-Object.freeze(player);
-
-export {player};
-
-export default class Singleton {
- static #instance;
-
- constructor() {
- if (Singleton.#instance) {
- return Singleton.#instance;
- }
-
- Singleton.#instance = this;
- }
- }
\ No newline at end of file
diff --git a/src/patterns/05-singleton/index.js b/src/patterns/05-singleton/index.js
index 0927bab..84d9ee5 100644
--- a/src/patterns/05-singleton/index.js
+++ b/src/patterns/05-singleton/index.js
@@ -1,5 +1,11 @@
export default class Singleton {
+ static #instance;
+
constructor() {
- // todo: implement logic
+ if (Singleton.#instance) {
+ return Singleton.#instance;
+ }
+
+ Singleton.#instance = this;
}
}
diff --git a/src/patterns/05-singleton/index.spec.js b/src/patterns/05-singleton/index.spec.js
index a0580ed..7b6ad81 100644
--- a/src/patterns/05-singleton/index.spec.js
+++ b/src/patterns/05-singleton/index.spec.js
@@ -2,6 +2,6 @@ import Singleton from './index.js';
describe('patterns/singleton', () => {
it('should return the same instance', () => {
- expect(new Singleton() === new Singleton()). toBeTruthy();
+ expect(new Singleton() === new Singleton()).toBeTruthy();
});
});
diff --git a/src/patterns/06-adapter/index.js b/src/patterns/06-adapter/index.js
index a61bc05..7c985e5 100644
--- a/src/patterns/06-adapter/index.js
+++ b/src/patterns/06-adapter/index.js
@@ -1,23 +1,24 @@
export const getArea = shape => {
- return shape.width * shape.height;
+ return shape.width * shape.height
};
export class Square {
constructor(size) {
- this.size = size;
+ this.size = size
}
}
export class Rectangle {
constructor(width, height) {
- this.width = width;
- this.height = height;
+ this.width = width
+ this.height = height
}
}
export class Adapter {
constructor(shape) {
- // todo: add implementation
+ this.width = shape.width ?? shape.size
+ this.height = shape.height ?? shape.size
}
}
diff --git a/src/patterns/07-bridge/example.js b/src/patterns/07-bridge/example.js
deleted file mode 100644
index 83122ad..0000000
--- a/src/patterns/07-bridge/example.js
+++ /dev/null
@@ -1,32 +0,0 @@
-interface Tv {
- getVolume(): number;
- setVolume(): number;
- //...
-}
-
-class Lg {
- getVolume() {};
- setVolume() {};
-}
-
-class Samsung {
- getVolume() {};
- setVolume() {};
-}
-
-class Sony {
- getVolume() {};
- setVolume() {};
-}
-
-class Remote {
- device: Tv;
-
- setDevice(device) {
- this.device = device;
- }
-
- changeVolumeByStep(step = 10) {
- this.device.setVolume(this.device.getVolume() + step)
- }
-}
\ No newline at end of file
diff --git a/src/patterns/07-bridge/index.js b/src/patterns/07-bridge/index.js
index 0c5419e..097b4de 100644
--- a/src/patterns/07-bridge/index.js
+++ b/src/patterns/07-bridge/index.js
@@ -1,21 +1,22 @@
export class RedColorsPallet {
- constructor () {
+ constructor() {
this.color = 'red';
}
}
export class GreenColorsPallet {
- constructor () {
+ constructor() {
this.color = 'green';
}
}
export class Notification {
- constructor () {
- // todo: add implementation
+ constructor(name, pallet) {
+ this.name = name;
+ this.colorsPallet = pallet;
}
- toString () {
+ toString() {
return `This is ${this.name} notification with ${this.colorsPallet.color} colors pallet`;
}
}
diff --git a/src/patterns/08-composite/example.js b/src/patterns/08-composite/example.js
deleted file mode 100644
index fd4a663..0000000
--- a/src/patterns/08-composite/example.js
+++ /dev/null
@@ -1,44 +0,0 @@
-class Fabric {
- items;
- draw() {
- // logic
- this.items.forEach(item => item.draw)
- }
-}
-
-class Node {
- draw() {
- //logic
- }
-}
-
-class Storage {
- items;
- draw() {
- // logic
- this.items.forEach(item => item.draw)
- }
-}
-
-class Graph {
- items;
- draw() {
- this.items.forEach(item => item.draw)
- }
-}
-
-const node = new Node();
-const node1 = new Node();
-const node2 = new Node();
-const node3 = new Node();
-const node4 = new Node();
-const storage = new Storage();
-const fabric = new Fabric();
-
-const graph = new Graph();
-
-graph.items = [storage, fabric, node];
-storage.items = [node1, node2];
-fabric.items = [node3, node4]
-
-graph.draw();
\ No newline at end of file
diff --git a/src/patterns/08-composite/index.js b/src/patterns/08-composite/index.js
index b41c387..b007758 100644
--- a/src/patterns/08-composite/index.js
+++ b/src/patterns/08-composite/index.js
@@ -3,8 +3,8 @@ export class Child {
this.value = value;
}
- getSum () {
- // todo: add implementation
+ getSum() {
+ return this.value;
}
}
@@ -13,8 +13,8 @@ export class Parent {
this.values = values;
}
- getSum () {
- // todo: add implementation
+ getSum() {
+ return this.values.reduce((acc, value) => acc + value.getSum(), 0)
}
}
diff --git a/src/patterns/09-decorator/index.js b/src/patterns/09-decorator/index.js
index 0c1ee33..cddddf2 100644
--- a/src/patterns/09-decorator/index.js
+++ b/src/patterns/09-decorator/index.js
@@ -1,20 +1,40 @@
-export class Milk {
- price = 2;
+class Additional {
+ price
- // todo: add implementation
+ constructor(coffee = null) {
+ if (this.constructor.name === 'Additional') {
+ throw new Error(`${this.constructor.name}: can not create instance of abstract class`);
+ }
+
+ this.coffePrice = coffee ? coffee.getPrice() : 0
+ }
+
+ getPrice () {
+ return this.price + this.coffePrice
+ }
+}
+
+export class Milk extends Additional {
+ price = 2
+
+ getPrice () {
+ return super.getPrice()
+ }
}
-export class Sugar {
- price = 1;
+export class Sugar extends Additional {
+ price = 1
- // todo: add implementation
+ getPrice () {
+ return super.getPrice()
+ }
}
export class Coffee {
- price = 5;
+ price = 5
getPrice () {
- return this.price;
+ return this.price
}
}
diff --git a/src/patterns/10-facade/example.js b/src/patterns/10-facade/example.js
deleted file mode 100644
index 20d39ab..0000000
--- a/src/patterns/10-facade/example.js
+++ /dev/null
@@ -1,29 +0,0 @@
-const facade = {
- player,
- tracker,
- logger,
- adPlanner,
-
- play() {
- this.adPlanner.playAd();
- this.tracker.sendTrack();
- this.player.play();
- },
-
- upVolume() {
- if(this.player.isMute()) {
- this.player.unmute();
- }
-
- this.player.setVolume(this.player.currentVolume + 1)
- },
-
- downVolume() {
-
- }
-}
-
-facade.play();
-facade.upVolume();
-
-
diff --git a/src/patterns/10-facade/index.js b/src/patterns/10-facade/index.js
index 0f6321d..5c19e42 100644
--- a/src/patterns/10-facade/index.js
+++ b/src/patterns/10-facade/index.js
@@ -1,6 +1,11 @@
export class Game {
- start () {
- // todo: add implementation
+ start() {
+ this.hero = new Hero('Barbarian');
+ this.location = new Location('darkForest');
+
+ this.location.addMonster(new Monster('demon'));
+ this.location.addMonster(new Monster('demon'));
+ this.location.addMonster(new Monster('undead'));
}
}
@@ -11,7 +16,7 @@ class Location {
this.name = name;
}
- addMonster (monster = {}) {
+ addMonster(monster = {}) {
this.monsters.push(monster);
}
}
diff --git a/src/patterns/11-flyweight/example.js b/src/patterns/11-flyweight/example.js
deleted file mode 100644
index 5eb63f7..0000000
--- a/src/patterns/11-flyweight/example.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const part = {
- characteristics: characteristics1,
- x: 0,
- y: 0,
-}
-
-const par1 = {
- characteristics: characteristics1,
- x: 0,
- y: 0,
-}
-
-const characteristics1 = {
- color: 'red',
- size: 'l',
- speed: '',
-}
-const characteristics2 = {
- color: 'blue',
- size: 'm',
- speed: '',
-}
-const characteristics3 = {
- color: 'green',
- size: 's',
- speed: '',
-}
\ No newline at end of file
diff --git a/src/patterns/11-flyweight/index.js b/src/patterns/11-flyweight/index.js
index a44aa44..436272a 100644
--- a/src/patterns/11-flyweight/index.js
+++ b/src/patterns/11-flyweight/index.js
@@ -1,18 +1,27 @@
class Flyweight {
- // todo: add implementation
+ constructor(info) {
+ this.info = info
+ }
}
export class ProductsStore {
- flyweights = {};
- products = [];
+ flyweights = {}
+ products = []
addProduct (productData = {}) {
- const productFlyweight = this.getOrCreateFlyweight(productData.info);
-
- // todo: add implementation
+ const productFlyweight = this.getOrCreateFlyweight(productData.info)
+ this.products.push({
+ ...productData,
+ info: productFlyweight
+ })
}
getOrCreateFlyweight (info = {}) {
- // todo: add implementation
+ const { name, color } = info
+ if (!this.flyweights[name + '_' + color]) {
+ this.flyweights[name + '_' + color] =
+ new Flyweight(info)
+ }
+ return this.flyweights[name + '_' + color]
}
}
diff --git a/src/patterns/12-proxy/example.js b/src/patterns/12-proxy/example.js
deleted file mode 100644
index 372b45c..0000000
--- a/src/patterns/12-proxy/example.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// const player = {
-// play() {
-// const film = FilmGetterProxy.getFilm()
-
-
-// }
-// }
-
-const FilmGetterProxy = {
- getFilm() {
- if (Cache.hasFilm()) {
- return Cache.getFilm();
- }
-
- return Loader.loadFilm();
- }
-}
-
-const Cache = {
-
-}
-
-const Loader = {
-
-}
-
-FilmGetterProxy.getFilm();
\ No newline at end of file
diff --git a/src/patterns/12-proxy/index.js b/src/patterns/12-proxy/index.js
index 0672507..cdc4e12 100644
--- a/src/patterns/12-proxy/index.js
+++ b/src/patterns/12-proxy/index.js
@@ -10,14 +10,14 @@ export class User {
}
export class ProxyUser {
- rights = [];
-
- constructor() {
- // todo: add implementation
+ constructor(user) {
+ this.user = user
}
write () {
- // todo: add implementation
+ if (this.user.rights.includes('admin'))
+ return this.user.write()
+ else return 'user does not have permissions to write'
}
}
diff --git a/src/patterns/13-chainOfResponsibility/example.js b/src/patterns/13-chainOfResponsibility/example.js
deleted file mode 100644
index 6dcea78..0000000
--- a/src/patterns/13-chainOfResponsibility/example.js
+++ /dev/null
@@ -1,54 +0,0 @@
-// action -> m -> m -> m -> reducer
-
-
-function m(next, action) {
- if (validate(action)) {
- next()
- }
-}
-
-
-const AuthorizationFilter = {
- next,
- setNext(next) {
- this.next = next
- },
-
- handle() {
- //logic
- if (success) {
- this.next.handle();
- }
- }
-}
-const RoleFilter = {
- next,
- setNext(next) {
- this.next = next
- },
-
- handle() {
- //logic
- if (success) {
- this.next.handle();
- }
- }
-}
-const LocationFilter = {
- next,
- setNext(next) {
- this.next = next
- },
-
- handle() {
- //logic
- if (success) {
- this.next.handle();
- }
- }
-}
-
-AuthorizationFilter.setNext(RoleFilter)
-RoleFilter.setNext(LocationFilter);
-
-AuthorizationFilter.handle(request);
\ No newline at end of file
diff --git a/src/patterns/13-chainOfResponsibility/index.js b/src/patterns/13-chainOfResponsibility/index.js
index d0af96a..aa5d6f3 100644
--- a/src/patterns/13-chainOfResponsibility/index.js
+++ b/src/patterns/13-chainOfResponsibility/index.js
@@ -1,51 +1,58 @@
class Handler {
- name = '';
- regExp = /./;
+ name = ''
+ regExp = /./
+ nextHandler = null
setNext (handler) {
- // todo: implement
+ this.nextHandler = handler
+ return this.nextHandler
}
- next (data) {
- // todo: implement
+ next(data) {
+ if (this.nextHandler)
+ return this.nextHandler.validate(data)
}
validate (data) {
- // todo: implement
+ if (this.regExp.test(data)) {
+ return this.next(data)
+ }
+
+ return `Validation rule "${this.name}" didn't pass for string "${data}"`
}
}
class MinLengthHandler extends Handler {
- name = 'min-length';
- regExp = /.{5}/;
+ name = 'min-length'
+ regExp = /.{5}/
}
class NumbersHandler extends Handler {
- name = 'numbers';
- regExp = /[0-9]/;
+ name = 'numbers'
+ regExp = /[0-9]/
}
class LettersHandler extends Handler {
- name = 'letter';
- regExp = /[a-z]/i;
+ name = 'letter'
+ regExp = /[a-z]/i
}
class CapitalLettersHandler extends Handler {
- name = 'capital-letters';
- regExp = /[A-Z]/;
+ name = 'capital-letters'
+ regExp = /[A-Z]/
}
class SpecialCharsHandler extends Handler {
- name = 'special-chars';
- regExp = /[`!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?~]/;
+ name = 'special-chars'
+ regExp = /[`!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?~]/
}
-const chainOfResponsibility = new MinLengthHandler();
+const chainOfResponsibility = new MinLengthHandler()
chainOfResponsibility
.setNext(new NumbersHandler())
.setNext(new LettersHandler())
.setNext(new CapitalLettersHandler())
- .setNext(new SpecialCharsHandler());
+ .setNext(new SpecialCharsHandler())
-export default chainOfResponsibility;
+export default chainOfResponsibility
diff --git a/src/patterns/14-command/example.js b/src/patterns/14-command/example.js
deleted file mode 100644
index b4b1ed6..0000000
--- a/src/patterns/14-command/example.js
+++ /dev/null
@@ -1,37 +0,0 @@
-class Editor {
- history = [];
- hasResources = true;
- queue = [];
-
- executeCommand(command) {
- if (this.hasResources) {
- command.execute()
- this.history.push(command);
- } else {
- this.queue.push(command);
- }
- }
-
- undo() {
- const lastCommand = this.history[this.history.length - 1];
- lastCommand.undo()
- this.history.length = this.history.length - 1;
- }
-}
-
-class Command {
- editor;
- undo() {
-
- }
- execute(){
-
- }
-}
-
-class CopyCommand {
- editor;
- execute() {
-
- }
-}
\ No newline at end of file
diff --git a/src/patterns/14-command/index.js b/src/patterns/14-command/index.js
index 2282d95..da72285 100644
--- a/src/patterns/14-command/index.js
+++ b/src/patterns/14-command/index.js
@@ -1,12 +1,20 @@
export class NextPage {
+ constructor(pagination) {
+ this.pagination = pagination
+ }
+
execute () {
- // todo: add implementation
+ this.pagination.nextPage()
}
}
export class PrevPage {
+ constructor(pagination) {
+ this.pagination = pagination
+ }
+
execute () {
- // todo: add implementation
+ this.pagination.prevPage()
}
}
@@ -14,20 +22,20 @@ export class Pagination {
currentPage = 1;
nextPage () {
- return this.currentPage += 1;
+ return this.currentPage += 1
}
prevPage () {
- return this.currentPage -= 1;
+ return this.currentPage -= 1
}
}
export class Button {
constructor (command) {
- // todo: add implementation
+ this.command = command
}
click () {
- // todo: add implementation
+ this.command.execute()
}
}
diff --git a/src/patterns/15-iterator/example.js b/src/patterns/15-iterator/example.js
deleted file mode 100644
index e2a3ee5..0000000
--- a/src/patterns/15-iterator/example.js
+++ /dev/null
@@ -1,19 +0,0 @@
-const MyCustomTree = {
- root = {
- children: [...],
- },
-
- iterator = {
- currentIndex = 0,
- getNext() {
- return
- },
- hasMore() {
-
- }
- }
-}
-
-MyCustomTree.getNext();
-MyCustomTree.getNext();
-MyCustomTree.iterator.hasMore();
diff --git a/src/patterns/15-iterator/index.js b/src/patterns/15-iterator/index.js
index 360fbc6..7d8f061 100644
--- a/src/patterns/15-iterator/index.js
+++ b/src/patterns/15-iterator/index.js
@@ -5,11 +5,15 @@ export class Range {
}
forEach (callback) {
- // todo: add implementation
+ return this.getRange().forEach(x => callback(x))
}
getRange () {
- // todo: add implementation
+ const rangeArr = []
+ for (let i = this.start; i <= this.end; i++) {
+ rangeArr.push(i)
+ }
+ return rangeArr
}
}
diff --git a/src/patterns/15-iterator/index.spec.js b/src/patterns/15-iterator/index.spec.js
index 39aba9a..5767e77 100644
--- a/src/patterns/15-iterator/index.spec.js
+++ b/src/patterns/15-iterator/index.spec.js
@@ -1,9 +1,20 @@
-import {Range} from './index.js';
+import { Range } from './index.js'
describe('patterns/iterator', () => {
it('should be able to return the range of numbers', () => {
- expect(new Range(1, 3).getRange()).toEqual([1, 2, 3]);
- expect(new Range(9, 15).getRange()).toEqual([9, 10, 11, 12, 13, 14, 15]);
+ expect(new Range(1, 3).getRange()).toEqual([1, 2, 3])
+ expect(new Range(9, 15).getRange()).toEqual([9, 10, 11, 12, 13, 14, 15])
+ });
+
+ it('should be able to call the callback function for each item of the range array', () => {
+ const cb = jest.fn()
+ const range = new Range(2, 4)
+
+ range.forEach(cb)
+
+ expect(cb).toHaveBeenCalledWith(2)
+ expect(cb).toHaveBeenCalledWith(3)
+ expect(cb).toHaveBeenCalledWith(4)
});
});
diff --git a/src/patterns/16-mediator/example.js b/src/patterns/16-mediator/example.js
deleted file mode 100644
index a43181e..0000000
--- a/src/patterns/16-mediator/example.js
+++ /dev/null
@@ -1,29 +0,0 @@
-const store = {
- dispatch(type, payload) {
-
- }
-}
-
-
-function Card() {
-
- return
- store.dispatch('buy', '123123')}>
-
-}
-
-function Cart() {
-
- return
-
- pizza store.dispatch('remove', '123123')}>
-
-
-}
-
-function Modal() {
-
- return
-
pizza store.dispatch('replace', '123123')}>
-
-}
\ No newline at end of file
diff --git a/src/patterns/16-mediator/imgs/friends.png b/src/patterns/16-mediator/imgs/friends.png
deleted file mode 100644
index ddb6da5..0000000
Binary files a/src/patterns/16-mediator/imgs/friends.png and /dev/null differ
diff --git a/src/patterns/16-mediator/index.js b/src/patterns/16-mediator/index.js
index 5d7339a..f6e6421 100644
--- a/src/patterns/16-mediator/index.js
+++ b/src/patterns/16-mediator/index.js
@@ -7,7 +7,7 @@ export class BillSharing {
}
addParticipant (participant) {
- // todo: add implementation
+ this.participants.push(participant)
}
getPaymentAmount() {
@@ -19,11 +19,14 @@ export class BillSharing {
}
share () {
- // todo: add implementation
+ this.participants.forEach(p => p.pay())
}
borrow (amount = 0) {
- // todo: add implementation
+ const participantsWithCash = this.participants.filter(p => p.cash)
+ participantsWithCash.forEach(p => {
+ p.borrow(amount / participantsWithCash.length)
+ })
}
}
@@ -35,10 +38,20 @@ export class User {
}
pay () {
- // todo: add implementation
+ const amount = this.billSharing.getPaymentAmount();
+ if (this.cash >= amount) {
+ this.billSharing.pay(amount)
+ this.cash -= amount
+ } else {
+ this.billSharing.pay(this.cash)
+ const diff = amount - this.cash
+ this.cash = 0;
+ this.billSharing.borrow(diff)
+ }
}
borrow (amount = 0) {
- // todo: add implementation
+ this.billSharing.pay(amount)
+ this.cash -= amount
}
}
diff --git a/src/patterns/17-memento/example.js b/src/patterns/17-memento/example.js
deleted file mode 100644
index 64f56d5..0000000
--- a/src/patterns/17-memento/example.js
+++ /dev/null
@@ -1,15 +0,0 @@
-const Origin = {
- state: { },
-
- save() {
-
- },
-
- restore(snapshot) {
-
- }
-}
-
-const snapshot = Origin.save();
-
-Origin.restore(snapshot);
\ No newline at end of file
diff --git a/src/patterns/17-memento/index.js b/src/patterns/17-memento/index.js
index 0233005..cff7221 100644
--- a/src/patterns/17-memento/index.js
+++ b/src/patterns/17-memento/index.js
@@ -1,13 +1,19 @@
-export class Memento {
- // todo: add implementation
+class Memento {
+ constructor(state) {
+ this.state = state
+ }
+
+ getState() {
+ return this.state
+ }
}
export class History {
- // todo: add implementation
+ snapshots = []
}
export class Hero {
- #name = '';
+ #name = ''
#state = {
level: 1,
@@ -15,27 +21,32 @@ export class Hero {
};
constructor(name = '', history = {}) {
- this.#name = name;
- this.history = history;
+ this.#name = name
+ this.history = history
}
get state () {
- return this.#state;
+ return this.#state
}
addSkill (skill) {
- this.#state.skills.push(skill);
+ this.#state.skills.push(skill)
}
increaseLevel () {
- this.#state.level += 1;
+ this.#state.level += 1
}
load (snapshot = {}) {
- // todo: add implementation
+ this.#state = snapshot.getState()
}
save () {
- // todo: add implementation
+ return new Memento({
+ ...this.state,
+ skills: [...this.state.skills]
+ })
}
}
+
+
diff --git a/src/patterns/18-observer/example.js b/src/patterns/18-observer/example.js
deleted file mode 100644
index ad9c8eb..0000000
--- a/src/patterns/18-observer/example.js
+++ /dev/null
@@ -1,19 +0,0 @@
-const store = {
- subscribers: new Map(),
-
- subscribe(callback) {
- this.subscribers.set(callback, callback);
-
- return () => this.subscribers.delete(callback);
- },
-
- notify() {
- this.subscribers.forEach(callback => callback());
- }
-}
-
-const unsubscribe = store.subscribe('1', () => console.log('storeChanged'));
-store.subscribe('2', () => console.log('storeChanged'));
-store.subscribe('3', () => console.log('storeChanged'));
-store.subscribe('4', () => console.log('storeChanged'));
-store.subscribe('5', () => console.log('storeChanged'));
\ No newline at end of file
diff --git a/src/patterns/18-observer/index.js b/src/patterns/18-observer/index.js
index 6474671..1a638de 100644
--- a/src/patterns/18-observer/index.js
+++ b/src/patterns/18-observer/index.js
@@ -1,23 +1,23 @@
export class NewsChannel {
- users = [];
+ users = []
subscribe (user) {
- // todo: add implementation
+ this.users.push(user)
}
notify (message = '') {
- // todo: add implementation
+ this.users.forEach(user => user.receiveMessage(message))
}
}
export class User {
- messagesHistory = [];
+ messagesHistory = []
constructor(name) {
- this.name = name;
+ this.name = name
}
receiveMessage (message = '') {
- // todo: add implementation
+ this.messagesHistory.push(message)
}
}
diff --git a/src/patterns/19-state/example.js b/src/patterns/19-state/example.js
deleted file mode 100644
index fda1904..0000000
--- a/src/patterns/19-state/example.js
+++ /dev/null
@@ -1,33 +0,0 @@
-const playerFacade = {
- player: {
-
- },
- state: pause,
-
- toggle() {
- const state = this.state.toggle(this.player);
-
- if (state) {
- this.state = state
- }
- }
-}
-
-const playing = {
- toggle(player) {
- player.pause();
- return pause;
- }
-}
-const pause = {
- toggle(player) {
- player.play();
- return playing;
- }
-}
-const buffering = {
- player,
- toggle(player) {
- // player.play();
- }
-}
\ No newline at end of file
diff --git a/src/patterns/19-state/imgs/lock.png b/src/patterns/19-state/imgs/lock.png
deleted file mode 100644
index d2d9925..0000000
Binary files a/src/patterns/19-state/imgs/lock.png and /dev/null differ
diff --git a/src/patterns/19-state/index.js b/src/patterns/19-state/index.js
index 4d1d588..b7316d0 100644
--- a/src/patterns/19-state/index.js
+++ b/src/patterns/19-state/index.js
@@ -1,46 +1,34 @@
-// todo: make refactoring, use State pattern
-class OldDigitalLock {
- state = {
- status: "locked",
- key: ""
- };
+class Locked {
+ status = 'locked'
- constructor(key = '') {
- this.state.key = key;
+ constructor(key) {
+ this.key = key
}
- toggle (combination = '') {
- if (this.state.status === "locked") {
- if (combination === this.state.key) {
- this.state.status = "unlocked";
- }
- return;
- }
-
- if (this.state.status === "unlocked") {
- if (combination) {
- this.state.key = combination;
- }
-
- this.state.status = "locked";
+ toggle(key = "") {
+ if (key === this.key) {
+ return new Unlocked()
}
}
}
-class Locked {
- // todo: add implementation
-}
-
class Unlocked {
- // todo: add implementation
+ status = 'unlocked'
+
+ toggle(key = "") {
+ if (key) {
+ return new Locked(key)
+ }
+ }
}
export class DigitalLock {
constructor(key = "") {
- // todo: add implementation
+ this.state = new Locked(key)
}
- toggle (combination = '') {
- // todo: add implementation
+ toggle (key = '') {
+ const newState = this.state.toggle(key)
+ this.state = newState ? newState : new Locked(key)
}
}
diff --git a/src/patterns/19-state/readme.md b/src/patterns/19-state/readme.md
index 020a456..26d3504 100644
--- a/src/patterns/19-state/readme.md
+++ b/src/patterns/19-state/readme.md
@@ -12,8 +12,6 @@
Данный класс работает по аналогии с кодовым замком, к-й часто можно встретить
на дверцах шкафчиков в гардеробах или на цепочках для паркинга велосипедов.
-
-
Ввод верной комбинации открывает замок и переводит его в состояние "unlock",
повторный ввод комбинации в состоянии "unlock", позволяет задать новую
комбинацию для открытия замка.
diff --git a/src/patterns/20-strategy/example.js b/src/patterns/20-strategy/example.js
deleted file mode 100644
index cc59d8a..0000000
--- a/src/patterns/20-strategy/example.js
+++ /dev/null
@@ -1,24 +0,0 @@
-const Table = {
- filter,
- sort,
-
- sortBy(columnName) {
- this.sort();
- },
-
- filterBy(value) {
- this.filter();
- }
-}
-
-function sort(columnName, items) {
-
-}
-function sort2(columnName, items) {
-
-}
-function sort3(columnName, items) {
-
-}
-
-Table.sort = sort3;
\ No newline at end of file
diff --git a/src/patterns/20-strategy/index.js b/src/patterns/20-strategy/index.js
index 1daaf22..6b8c31f 100644
--- a/src/patterns/20-strategy/index.js
+++ b/src/patterns/20-strategy/index.js
@@ -1,40 +1,49 @@
-export class Club {
- speed = 0.5;
- damage = 20;
+class Weapon {
+ speed = 0
+ damage = 0
+
attack (monster) {
return this.damage * this.speed - monster.armor;
}
}
-export class Sword {
- speed = 1;
- damage = 15;
+export class Club extends Weapon {
+ speed = 0.5
+ damage = 20
+ attack (monster) {
+ return super.attack(monster)
+ }
+}
+
+export class Sword extends Weapon {
+ speed = 1
+ damage = 15
attack (monster) {
- // todo: add implementation
+ return super.attack(monster)
}
}
-export class MagicWand {
- speed = 2;
- damage = 8;
+export class MagicWand extends Weapon {
+ speed = 2
+ damage = 8
attack (monster) {
- // todo: add implementation
+ return super.attack(monster)
}
}
export class Hero {
- constructor(name) {
- this.name = name;
- // todo: add implementation
+ constructor(name, weapon) {
+ this.name = name
+ this.weapon = weapon
}
hit (monster) {
- // todo: add implementation
+ return this.weapon.attack(monster)
}
}
export class Monster {
constructor(armor = 0) {
- this.armor = armor;
+ this.armor = armor
}
}
diff --git a/src/patterns/21-templateMethod/example.js b/src/patterns/21-templateMethod/example.js
deleted file mode 100644
index 5f506e5..0000000
--- a/src/patterns/21-templateMethod/example.js
+++ /dev/null
@@ -1,36 +0,0 @@
-class Node {
- draw() {
- this.calculateSize();
- this.formatText();
- this.drawChildren();
- };
-
- calculateSize(){
- throw new Error('implement');
- };
- formatText(){
- throw new Error('implement');};
- drawChildren(){
- throw new Error('implement');};
-}
-
-
-class FabricNode extends Node {
- calculateSize() {};
- formatText() {};
- drawChildren() {};
-}
-
-class StorageNode extends Node {
- calculateSize() {};
- formatText() {};
- drawChildren() {};
-}
-
-const fabric = new FabricNode();
-
-function draw(rootNode) {
- rootNode.draw();
-}
-
-draw(fabric);
\ No newline at end of file
diff --git a/src/patterns/21-templateMethod/index.js b/src/patterns/21-templateMethod/index.js
index 36fadeb..ca3fee1 100644
--- a/src/patterns/21-templateMethod/index.js
+++ b/src/patterns/21-templateMethod/index.js
@@ -1,66 +1,55 @@
class HotDrinksPot {
- // todo: add implementation
-}
-
-// todo: make refactoring via template method pattern
-export class TeaPot {
- algorithmSteps = {};
+ algorithmSteps = {}
constructor() {
- this.prepareRecipe();
+ this.prepareRecipe()
}
prepareRecipe () {
- this.boilWater();
- this.brewTea();
- this.pourInCup();
- this.addLemon();
+ this.boilWater()
+ this.brew()
+ this.pourInCup()
+ this.addCondiments()
}
+ boilWater() {/*A*/}
+ brew() {/*A*/}
+ pourInCup() {/*A*/}
+ addCondiments() {/*A*/}
+}
+
+export class TeaPot extends HotDrinksPot {
boilWater () {
- this.algorithmSteps.boilWater = 'Boiling water';
+ this.algorithmSteps.boilWater = 'Boiling water'
}
- brewTea () {
- this.algorithmSteps.brewTea = 'Steeping the tea';
+ brew () {
+ this.algorithmSteps.brew = 'Steeping the tea'
}
pourInCup () {
- this.algorithmSteps.pourInCup = 'Pouring into cup';
+ this.algorithmSteps.pourInCup = 'Pouring into cup'
}
- addLemon () {
- this.algorithmSteps.addLemon = 'Adding Lemon';
+ addCondiments () {
+ this.algorithmSteps.addCondiments = 'Adding Lemon'
}
}
-export class CoffeePot {
- algorithmSteps = {};
-
- constructor() {
- this.prepareRecipe();
- }
-
- prepareRecipe () {
- this.boilWater();
- this.brewCoffee();
- this.pourInCup();
- this.addSugarAndMilk();
- }
-
+export class CoffeePot extends HotDrinksPot {
boilWater () {
- this.algorithmSteps.boilWater = 'Boiling water';
+ this.algorithmSteps.boilWater = 'Boiling water'
}
- brewCoffee () {
- this.algorithmSteps.brewCoffee = 'Dripping Coffee through filter';
+ brew () {
+ this.algorithmSteps.brew = 'Dripping Coffee through filter'
}
pourInCup () {
- this.algorithmSteps.pourInCup = 'Pouring into cup';
+ this.algorithmSteps.pourInCup = 'Pouring into cup'
}
- addSugarAndMilk () {
- this.algorithmSteps.addSugarAndMilk = 'Adding Sugar and Milk';
+ addCondiments () {
+ this.algorithmSteps.addCondiments = 'Adding Sugar and Milk'
}
}
diff --git a/src/patterns/22-visitor/example.js b/src/patterns/22-visitor/example.js
deleted file mode 100644
index 008f56b..0000000
--- a/src/patterns/22-visitor/example.js
+++ /dev/null
@@ -1,20 +0,0 @@
-const PdfMaker = {
- makeFabricPdf(fabric) {
-
- },
- makeStoragePdf(storage) {
-
- },
- makeCirclePdf(circle) {
-
- },
-}
-
-const Fabric = {
-}
-const Storage = {
-}
-const Circle = {
-}
-
-Visitor.makeFabricPdf(Fabric);
\ No newline at end of file
diff --git a/src/patterns/22-visitor/index.js b/src/patterns/22-visitor/index.js
index f8228d2..4b49684 100644
--- a/src/patterns/22-visitor/index.js
+++ b/src/patterns/22-visitor/index.js
@@ -1,17 +1,18 @@
export class Visitor {
constructor(compositeItem) {
- this.compositeItem = compositeItem;
- this.init();
+ this.compositeItem = compositeItem
+ this.init()
}
init () {
- this.addGetSize();
-
- // todo: add implementation
+ this.addGetSize()
+ this.compositeItem.children.forEach(child => child.accept(Visitor))
}
addGetSize () {
- // todo: add implementation
+ this.compositeItem.getSize = () => {
+ return 1 + this.compositeItem.children.reduce((sum, child) => sum + child.getSize(), 0)
+ }
}
}
@@ -21,12 +22,12 @@ export class Comment {
content = '',
children = []
} = {}) {
- this.id = id;
- this.content = content;
- this.children = children;
+ this.id = id
+ this.content = content
+ this.children = children
}
accept (Visitor) {
- new Visitor(this);
+ new Visitor(this)
}
}