Skip to content
This repository has been archived by the owner on Dec 10, 2022. It is now read-only.

Commit

Permalink
Iterator, observer and Strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
NSnietol committed Jan 12, 2019
1 parent d062e47 commit 0c842d1
Show file tree
Hide file tree
Showing 16 changed files with 378 additions and 1 deletion.
34 changes: 34 additions & 0 deletions Node.js-design-patterns/Behaviorals/Command/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
var { writeFile } = require('fs');
var path = require('path');

class ExitCommand {

get name() {
return 'exit... bye!';
}

execute() {
process.exit(0);
}

}

class CreateCommand {

constructor(fileName, text) {
this.fileName = fileName;
this.body = text;
this.fullPath = path.join(__dirname, fileName);
}

get name() {
return `create ${this.fileName}`;
}

execute() {
writeFile(this.fullPath, this.body, f => f);
}

}

module.exports = { ExitCommand, CreateCommand };
10 changes: 10 additions & 0 deletions Node.js-design-patterns/Behaviorals/Command/conductor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Conductor {

run(command) {
console.log(`Executing command: ${command.name}`);
command.execute();
}

}

module.exports = new Conductor();
35 changes: 35 additions & 0 deletions Node.js-design-patterns/Behaviorals/Command/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
var conductor = require('./conductor');
var { ExitCommand, CreateCommand } = require('./commands');

var { createInterface } = require('readline');
var rl = createInterface({
input: process.stdin,
output: process.stdout
});

console.log('create <fileName> <text> | exit');
rl.prompt();

rl.on('line', input => {

var [ commandText, ...remaining ] = input.split(' ')
var [ fileName, ...fileText ] = remaining
var text = fileText.join(' ')

switch(commandText) {

case "exit":
conductor.run(new ExitCommand());
break;

case "create" :
conductor.run(new CreateCommand(fileName, text));
break;

default :
console.log(`${commandText} command not found!`);
}

rl.prompt();

});
14 changes: 14 additions & 0 deletions Node.js-design-patterns/Behaviorals/Iterator/InventoryItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class InventoryItem {

constructor(name, price) {
this.name = name;
this.price = price;
}

writeLn() {
process.stdout.write(`${this.name}: $${this.price}`);
}

}

module.exports = InventoryItem;
42 changes: 42 additions & 0 deletions Node.js-design-patterns/Behaviorals/Iterator/Iterator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
class Iterator {

constructor(items=[]) {
this.index = 0;
this.items = items;
}

first() {
var [first] = this.items;
return first;
}

last() {
var [last] = [...this.items].reverse();
return last;
}

hasNext() {
return this.index < this.items.length - 1;
}

current() {
return this.items[this.index];
}

next() {
if (this.hasNext()) {
this.index += 1;
}
return this.current();
}

prev() {
if (this.index !== 0) {
this.index -= 1;
}
return this.current();
}

}

module.exports = Iterator;
49 changes: 49 additions & 0 deletions Node.js-design-patterns/Behaviorals/Iterator/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
var InventoryItem = require('./InventoryItem');
var Iterator = require('./Iterator');

require('readline').emitKeypressEvents(process.stdin);
process.stdin.setRawMode(true);

console.log('Press any direction key...');

var inventory = new Iterator([
new InventoryItem("Poles", 9.99),
new InventoryItem("Skis", 799.99),
new InventoryItem("Boots", 799.99),
new InventoryItem("Burgers", 5.99),
new InventoryItem("Fries", 2.99),
new InventoryItem("Shake", 4.99),
new InventoryItem("Jeans", 59.99),
new InventoryItem("Shoes", 39.99)
]);

process.stdin.on('keypress', (str, key) => {

process.stdout.clearLine();
process.stdout.cursorTo(0);

switch(key.name) {

case 'right' :
inventory.next().writeLn();
break;

case 'left' :
inventory.prev().writeLn();
break;

case 'down' :
inventory.last().writeLn();
break;

case 'up' :
inventory.first().writeLn();
break;

case 'c' :
if (key.ctrl) {
process.exit()
}
}

});
13 changes: 13 additions & 0 deletions Node.js-design-patterns/Behaviorals/Observer/Mall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Mall {

constructor() {
this.sales = [];
}

notify(storeName, discount) {
this.sales.push({ storeName, discount });
}

}

module.exports = Mall;
12 changes: 12 additions & 0 deletions Node.js-design-patterns/Behaviorals/Observer/Shopper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class Shopper {

constructor(name) {
this.name = name;
}

notify(storeName, discount) {
console.log(`${this.name}, there is a sale at ${storeName}! ${discount}% off everything!`);
}
}

module.exports = Shopper;
18 changes: 18 additions & 0 deletions Node.js-design-patterns/Behaviorals/Observer/Store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class Store {

constructor(name) {
this.name = name;
this.subscribers = [];
}

subscribe(observer) {
this.subscribers.push(observer);
}

sale(discount) {
this.subscribers.forEach(observer => observer.notify(this.name, discount));
}

}

module.exports = Store;
26 changes: 26 additions & 0 deletions Node.js-design-patterns/Behaviorals/Observer/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
var Store = require('./Store');
var Shopper = require('./Shopper');
var Mall = require('./Mall');

var catsAndThings = new Store("Cats & Things");
var insAndOuts = new Store("Ins and Outs");

var alex = new Shopper("Alex");
var eve = new Shopper("Eve");
var sharon = new Shopper("Sharon");
var mike = new Shopper("Mike");

var valleyMall = new Mall();

catsAndThings.subscribe(alex);
catsAndThings.subscribe(eve);
catsAndThings.subscribe(mike);
catsAndThings.subscribe(valleyMall);

insAndOuts.subscribe(sharon);
insAndOuts.subscribe(valleyMall);

catsAndThings.sale(20);
insAndOuts.sale(50);

console.log( valleyMall.sales );
36 changes: 36 additions & 0 deletions Node.js-design-patterns/Behaviorals/Strategy/LogStrategy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
var path = require('path');
var { appendFile } = require('fs');
var morse = require('morse');

class LogStrategy {

static toMorseCode(timestamp, message) {
var morseCode = morse.encode(message);
console.log(morseCode);
}

static noDate(timestamp, message) {
console.log(message);
}

static toFile(timestamp, message) {
var fileName = path.join(__dirname, 'logs.txt');
appendFile(fileName, `${timestamp} - ${message} \n`, error => {
if (error) {
console.log('Error writing to file');
console.error(error);
}
})
}

static toConsole(timestamp, message) {
console.log(`${timestamp} - ${message}`);
}

static none() {

}

}

module.exports = LogStrategy;
27 changes: 27 additions & 0 deletions Node.js-design-patterns/Behaviorals/Strategy/Logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
var LogStrategy = require('./LogStrategy');
var config = require('./config');

class Logger {

constructor(strategy='toConsole') {
this.logs = [];
this.strategy = LogStrategy[strategy];
}

get count() {
return this.logs.length
}

changeStrategy(newStrategy) {
this.strategy = LogStrategy[newStrategy];
}

log(message) {
const timestamp = new Date().toISOString()
this.logs.push({ message, timestamp })
this.strategy(timestamp, message);
}

}

module.exports = new Logger(config.logs.strategy);
5 changes: 5 additions & 0 deletions Node.js-design-patterns/Behaviorals/Strategy/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"logs": {
"strategy": "toMorseCode"
}
}
11 changes: 11 additions & 0 deletions Node.js-design-patterns/Behaviorals/Strategy/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var logger = require('./Logger');

logger.log('Hello World');
logger.log('Hi World');
logger.log('Yo World');

logger.changeStrategy('none');

logger.log('Hello World');
logger.log('Hi World');
logger.log('Yo World');
33 changes: 33 additions & 0 deletions Node.js-design-patterns/Behaviorals/Strategy/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion Node.js-design-patterns/Behaviorals/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,16 @@ Intent : "Avoid coupling the sender of a request to its receiver by giving than

## Command

Intent : "Encapsulate a request as an object, thereby letting you parameterize with different requests, queue or log requests, and support undoable operations."
Intent : "Encapsulate a request as an object, thereby letting you parameterize with different requests, queue or log requests, and support undoable operations."

## Iterator

Intent : "Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation."

## Observer

Intent : "Define a one-to-many dependency between objects so that when object changes state, all its dependents are notified and updated automatically."

## Strategy

Intent: "Define a family or algorithms, encapsulate each one, and make then interchangeable. Strategy lets the algorithm vary independently from clients that use it."

0 comments on commit 0c842d1

Please sign in to comment.