Make it Real Elite — eighth week — Design patterns

Alejandro Estrada
Jul 27, 2017 · 3 min read

The design patterns were something that I have never heard about it but I had implemented one of them on my beginnings without knowing that it was a design pattern. It was on my first personal project that I develop used to improve my knowledge, it was with angular and there was a moment where I decide to use something call factory that would help me to reuse some code.


The design patterns:

Design patterns are solutions to general problems in software design. We are going to go throw some of them.

Factory:

The factory method will create objects as a template method; a supperclass specifies the standard behavior and delegates the creation detail to subclasses.

const ProviderFactory = {
Provider (type) {
return Object.create(this.type[type])
},
type: {
clothes: {
materials () {
return [‘xyz’, ‘abc’, ‘def’]
},
taxId () {
return [‘0%’, ‘19%’]
}
},
food: {
products () {
return [‘burger’, ‘hot dog’, ‘sandwich’]
},
taxId () {
return [‘0%’, ‘19%’]
}
}
}
}
const manufacturer = ProviderFactory.Provider(‘clothes’);console.log(manufacturer.materials());console.log(manufacturer.taxId());const foodProvider = ProviderFactory.Provider(‘food’);console.log(foodProvider.products());console.log(foodProvider.taxId());

Object Pool:

The object pool will reuse objects, it means that there is a pool of objects where the user asks for one of them, after the task is done the object will return to the pool so it can be used again. This is used in situations where the cost of initializing a class instance is high. If all the objects of the pool are requested, it can create a new one or we can restrict the number of objects created.

Adapter:

Adapter pattern works as a bridge between to incompatible, interfaces. We can use it to connect two different type of data base, a SQL and a NOSQL. In this example, we are going to have two variables with the same methods but with different results, so the only thing is to define the adapter to use to connect to each one.

const sqlExample = [{name: ‘test’, id: 1}, {name: ‘test2’, id: 2}];
const noSqlExample = [{name: ‘test no sql’, id: 10}, {name: ‘test no sql’, id: 20}];
const SqlAdapter = {
findById(id) {
return new Promise((resolve) => {
resolve(sqlExample.filter((val) => {
return val.id === id
}))
})
},
add(item) {
sqlExample.push(item);
}
}
const NoSqlAdapter = {
findById(id) {
return new Promise((resolve) => {
resolve(noSqlExample.filter((val) => {
return val.id === id
}))
})
},
add(item) {
noSqlExample.push(item)
}
}
class User {
constructor(adapter) {
this.adapter = adapter;
}

findById(id) {
return new Promise((resolve) => {
resolve(this.adapter.findById(id))
})
};
add(item) {
this.adapter.add(item);
}
}
const user = new User(SqlAdapter);
user.add({name: ‘Test’, id: 11});
user.findById(1)
.then((user) => {
console.log(user)
})

Decorator:

The decorator is a design pattern that allows us to add new functionality to an existing object without altering its structure. This pattern wraps the original class and provides additional functionality keeping the class methods signature intact. On JavaScript, the decorators are not defined, to use it you must use babel or another compiler that allows them.

Chain of responsibility:

The chain of responsibility creates a chain of receiver objects for a request. Each receiver contains reference to another receiver and if one object cannot handle the request it passes to the next. The best way to understand it is with an ATM example where there are different bills and an exact value to withdraw.

class Request {
constructor(amount) {
this.amount = amount;
}

get(bill) {
const count = Math.floor(this.amount / bill);
this.amount -= count * bill;
console.log(`Dispense ${count} $${bill} bills`);
return this;
}
}
const atm = new Request(340);
atm.get(100).get(50).get(40).get(10);

Observer:

Observer pattern is used when some objects depends of other object so what they do is to subscribe to it, and if it has some changes, it notifies them so, them can make their respective changes.

class Click {
constructor() {
this.handlers = [];
}
subscribe(fn) {
this.handlers.push(fn);
};
unsubscribe(fn) {
this.handlers = this.handlers.filter(item => item !== fn);
};
fire(thisObj) {
const scope = thisObj || null;
this.handlers.forEach((item) => {
item(scope);
});
}
}
const clickHandler = item => {
console.log(`Fired: ${item}`);
}
const click = new Click();
click.subscribe(clickHandler);
click.fire(‘Event #1’);
click.unsubscribe(clickHandler);
click.fire(‘Event #2’);
click.subscribe(clickHandler);
click.fire(‘Event #3’);

Visitor:

The visitor pattern is used to change the executing algorithm of an element class. The element object must accept the visitor object so that visitor can handle the operation on the element object