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
- -
-} - -function Cart() { - - return
-
    -
  • pizza
  • -
-
-} - -function Modal() { - - return
-
  • pizza
  • -
    -} \ 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 @@ Данный класс работает по аналогии с кодовым замком, к-й часто можно встретить на дверцах шкафчиков в гардеробах или на цепочках для паркинга велосипедов. -![](/assets/lock.png) - Ввод верной комбинации открывает замок и переводит его в состояние "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) } }