I have a class - call it ThankYou that delivers these. Based on the different implementations, generic or Facebook, I need to deliver customized layout. Right now, I am building the HTML in JS and delivering the layout.
1) Sign up for email newsletters (for generic and Facebook implementation)
2) Teaser content (for generic implementation)
3) Facebook like(for Facebook ThankYou implementation)
Which design pattern do you think this is better implemented using - Factory or Mediator? I am just starting to utilize some design patterns in my code and would like to start off on the right foot.
Some notes:
a) Although the functionality might be the same, the layout might be different for generic and Facebook
If I don't use a design pattern, I could easily do this using an 'if' statement, but I am just looking for a more elegant solution.
I think that Factory more suitable in this case. You have base class (interface) called IThankYou that implements common methods and two classes extending base functionality. Factory stores mapping between type and class.
Small example code:
function IThankYou () {}
IThankYou.prototype = {
templates: { // this is common field for all instances extending this class
like: '<div class="b-like">Like</div>',
},
like: function () { throw "Unimplemented" }, // this method is not implemented in base class
commonMethod: function () { } // this is common method
};
function GenericThankYou (someParam) { this.someParam = someParam; };
GenericThankYou.prototype = new IThankYou;
GenericThankYou.prototype.like = function () {
// there you could use base class fields and methods
this.commonMethod();
};
function FacebookThankYou (someParam) { this.someParam = someParam; };
FacebookThankYou.prototype = new IThankYou;
FacebookThankYou.prototype.like = function () {
// there you could use base class templates map
};
var ThankYouFactory = {
typeMap: {
'facebook' : FacebookThankYou,
'generic' : GenericThankYou
},
getConstructor: function (type) {
return this.typeMap[type];
}
};
ThankYouFactory.getConstructor('facebook')(ctorParam);
ThankYouFactory.getConstructor('generic')(ctorParam);
Related
since JS does not support abstract classes or inheritance, every time we want to add a new type to be created when using factory pattern, we will have to modify the code which mean we violate the open-close principle. for example, in the snapshot bellow - if we want to add a new employee type like Marketing, we will have to update the switch statement which is violation of the open-close principle. Is there any workaround to use the factory pattern without violation open-close principle?
function Accountant(){
console.log('I am accountant');
}
function Developer(){
console.log('I am developer');
}
function Sales(){
console.log('I am sales');
}
function CreateEmployee(employee){
switch(employee){
case('accountant'): return new Accountant();
case('developer'): return new Developer()
case('sales'): return new Sales();
}
}
if we want to add a new employee type, we will have to update the switch statement which is violation of the open-close principle.
No, it doesn't. The OCP is not about forbidding to update code. If we want to implement a new feature, we of course need to touch the code of the program. The OCP is about designing your interfaces so that your program can be easily extended without changing code all over the place - ideally you only have to provide the new code, and change the configuration of the program to make use of it - or if this is not configurable, change only the high-level building blocks.
I would argue that the factory pattern even facilitates application of the OCP - don't think about changes to the factory function, think about the modules that use it. Instead of changing all the code in all the modules that instantiates employee objects, all you need to do is to supply a different factory to them.
A step in the right direction is to create an employeeType object that holds the constructors:
const employeeType = {
Accountant,
Developer,
Salesperson
};
// console.log(new (employeeType["Accountant"])());
// Abstract away the hard-coded type above; the below randomization is strictly for demo purpose
const employeeTypeKeys = Object.keys(employeeType);
const employeeTypeIndex = Math.floor(employeeTypeKeys.length * Math.random());
console.log(new (employeeType[employeeTypeKeys[employeeTypeIndex]])());
function Accountant(){
console.log('I am an accountant');
}
function Developer(){
console.log('I am a developer');
}
function Salesperson(){
console.log('I am a salesperson');
}
I would argue the pattern isn't exactly something I'd like to extend but it's possible.
Say you have access to the CreateEmployee function alone and you'd want to extend it so you can also add Engineers.
import CreateEmployee from "./employee.js";
function Engineer(){
console.log("I'm an Engineer");
}
function CreateEmployeeAndEngineer(employeeType){
if(employeeType === 'Engineer') return new Engineer();
else {
return CreateEmployee(employeeType);
}
}
Simple (ehh... not really) function composition.
However, there's very little value for it in Javascript since it's untyped. Then of course functions, and therefore constructors, are first-class citizens and can be easily passed down to the new operator.
since JS does not support abstract classes or inheritance
Javascript does support inheritance through it's concept of prototype chain.
You could implement the Factory method pattern if you'd want.
If you want new instances to be created on the fly, you should use Object literals. Review the following design for an idea on how you may, or may not, want to go about this:
function ucFirst(string){
const s = string.split('');
return s.shift().toUpperCase()+s.join('');
}
function InstanceController(){
this.instances = [];
this.add = (name, obj)=>{
this.instances.push({name:name, obj:obj});
return this;
}
this.get = name=>{
for(let o of this.instances){
if(o.name === name){
return o.obj;
}
}
return false;
}
this.remove = name=>{
for(let i=0,a=this.instances,l=a.length; i<l; i++){
if(a[i].name === name){
a.splice(i, 1);
break;
}
}
return this;
}
}
const ic = new InstanceController;
const data1 = {
data:'could be from database',
more:'sure there can be more data',
numberTest: 2
}
const data2 = {test:'just a test'};
ic.add('developer', data1).add('accountant', {testing:'see'});
let dev = ic.get('developer'), aco = ic.get('accountant');
if(dev)console.log(dev);
if(aco)console.log(aco);
console.log(ic.get('nope'));
ic.remove('accountant'); aco = ic.get('accountant');
console.log(aco);
I have found a GitHub repository full of JavaScript algorithms and data types. The thing is, everything is written in OOP. I myself, prefer a more FP approach using small, reusable functions. What are some best practices to convert classes to smaller consumable functions?
For now, I can come up with the following working example. Is this the way to go?
OOP:
class LinkedListNode {
constructor(value, next = null) {
this.value = value;
this.next = next;
}
toString(callback) {
return callback ? callback(this.value) : `${this.value}`;
}
}
FP:
function toString(value, callback) {
return callback ? callback(value) : `${value}`;
}
function Node(value, next = null) {
return {
value,
next,
toString(callback) {
return toString(value, callback);
}
};
}
In your second example you still have a method attached to each instance, which is not ideal as soon as you want to reuse this method on a compatible interface. Also it does not play well with many FP js libraries.
To make it clear from the outside that it is not a constructor function, make it start lower case and add a prefix like create for example.
Make functions as pure as possible and do not mix code composition logic (compose, curry) with the business logic. (I talk about callback having nothing to do inside toString)
I am adding export to clearly show that at least 2 functions need to be exported.
export { nodeToString, createNode };
function nodeToString(node) {
return `${node.value}`;
}
function createNode(value, next = null) {
return {
value,
next
};
}
It would be used like this
import { nodeToString, createNode } from "./x.js";
const node = createNode(`myvalue`);
const string = nodeToString(node);
I have a class with a member variable of type object. This object has a fixed number of fields. I'm trying to decide if I should use one setter function or multiple to mutate these fields.
To make the question more concrete, I've written the following class to model a simple organizational management structure in two different ways:
Multiple Setter Functions
class Management {
constructor() {
this.numberOfManagers = 100;
this.salaryDetails = {
regionalManagerSalary: 80000,
stateManagerSalary: 110000,
executiveManagerSalary: 200000
};
}
setRegionalManagerSalary(salary) {
this.salaryDetails.regionalManagerSalary = salary;
}
setStateManagerSalary(salary) {
this.salaryDetails.stateManagerSalary = salary;
}
setExecutiveManagerSalary(salary) {
this.salaryDetails.executiveManagerSalary = salary;
}
}
const management = new Management();
management.setRegionalManagerSalary(100000);
management.setStateManagerSalary(120000);
management.setExecutiveManagerSalary(210000);
One Setter Function
class Management {
constructor() {
this.numberOfManagers = 100;
this.salaryDetails = {
regionalManagerSalary: 80000,
stateManagerSalary: 110000,
executiveManagerSalary: 200000
};
}
setManagerSalary(typeOfManagerSalary, salary) {
this.salaryDetails[typeOfManagerSalary] = salary;
}
}
const management = new Management();
management.setManagerSalary('regionalManagerSalary', 100000);
management.setManagerSalary('stateManagerSalary', 120000);
management.setManagerSalary('executiveManagerSalary', 210000);
Would implementation 1. be better or would implementation 2. be better?
I will always consider the higher readability approach if it doesn't trade off a lot of writability. The second one is more generic but the first one is more clear.
So I think the first one is better as it is more clear that there are only 3 fields in salaryDetails. Just consider you are not the author and when you see the second one, you have no idea how many fields there will be in salaryDetails as someone could just call management.setManagerSalary('someNewSalary', 100000); somewhere to add some new fields.
Unless you have more than one Management objects and each of them might have some specific fields under salaryDetails, I don't think the second approach is better.
My recommendation would be to have one method say setSalaryDetails which will take salary object as input which you can set directly. Something like -
setSalaryDetails(salaryDetails){this.salaryDetails = salaryDetails; }
When you invoke this method you can appropriately create this object with those fields set that you will pass to it.
It is better to not have any setter at all. Initialize all the required properties in the constructor (let the constructor require arguments for this).
The code you posted it not OOP but procedural code under disguise. If you want to make it OOP then the code must stay where the data is, i.e. in the class.
As a first improvement step, your code should look like this:
class Management {
constructor(nb, regionalSalary, stateSalary, executiveSalary) {
this.numberOfManagers = nb;
this.salaryDetails = {
regionalManagerSalary: regionalSalary,
stateManagerSalary: stateSalary,
executiveManagerSalary: executiveSalary
};
}
}
const management = new Management(100, 100000, 120000, 210000);
Shorter, much cleaner, less error prone.
The fragment you posted is not enough to tell what you want to achieve but the new signature of the constructor tells me that you are mixing too many responsibilities into a single class.
A cleaner design is to use separate classes for each manager type:
/* abstract */ class Manager {
constructor(salary) {
this.salary = salary;
}
}
class RegionalManager extends Manager { }
class StateManager extends Manager { }
class ExecutiveManager extends Manager { }
class Management {
constructor(nb, regionalManager, stateManger, executiveManager) {
this.numberOfManagers = nb;
this.managers = {
regionalManager: regionaManager,
stateManager: stateManager,
executiveManager: executiveManager
};
}
}
const management = new Management(
100,
new RegionalManager(100000),
new StateManager(120000),
new ExecutiveManager(210000)
);
You can now implement the logic common to all manager types in class Manager, the logic that is specific to each manager type in its class and the logic that handles the managers by number, without caring about their individual characteristics, in class Management. This way the code uses less if and switch conditions, is easier to read, understand and develop further.
As an example of what I'd like to do, in Draft.js I'd like to allow the users to include a slideshow of images in the page that could change externally later on. So if there is a slideshow defined in my app, the user could select that slideshow to put in their page, and if the images were changed later then they would automatically update on the page. A visual representation in the editor would a nice-to-have as well. Am I asking too much or is this possible in Draft.js?
It never fails. I post a question and almost immediately I find something that might answer my question. Draft.js has what is called "decorators", which are currently documented here: https://draftjs.org/docs/advanced-topics-decorators.html
Basically you'd create a series of decorators using functions / components. Strategy takes a function, component is obvious.
const compositeDecorator = new CompositeDecorator([
{
strategy: handleStrategy,
component: HandleSpan,
},
{
strategy: hashtagStrategy,
component: HashtagSpan,
},
]);
Strategies can be defined using regexes. This enables you to write your own syntax or use that of a template engine's for embedding widgets. The strategies in the documentation are a fairly good example:
// Note: these aren't very good regexes, don't use them!
const HANDLE_REGEX = /\#[\w]+/g;
const HASHTAG_REGEX = /\#[\w\u0590-\u05ff]+/g;
function handleStrategy(contentBlock, callback, contentState) {
findWithRegex(HANDLE_REGEX, contentBlock, callback);
}
function hashtagStrategy(contentBlock, callback, contentState) {
findWithRegex(HASHTAG_REGEX, contentBlock, callback);
}
function findWithRegex(regex, contentBlock, callback) {
const text = contentBlock.getText();
let matchArr, start;
while ((matchArr = regex.exec(text)) !== null) {
start = matchArr.index;
callback(start, start + matchArr[0].length);
}
}
And then here are the components:
const HandleSpan = (props) => {
return <span {...props} style={styles.handle}>{props.children}</span>;
};
const HashtagSpan = (props) => {
return <span {...props} style={styles.hashtag}>{props.children}</span>;
};
I have a custom-built JavaScript framework that I inherited from the person that worked here before me. What I can say is that it's a web app of sorts that leverages jQuery.
There are a lot of events being fired by various objects that I'd like to document, but I'm unsure of how to do this. I've seen JSDoc 3's examples on the #listens page, but they seem to be oriented more towards a module development pattern, so I'm unsure of how to apply them to the pattern here:
ClassA.js:
var ClassA = function (args) {
//constructor stuff goes here... usually punctuated with:
this.listenForEvents();
};
ClassA.prototype.listenForEvents = function () {
$(document).on("someEvent", function (e, args) {
//Event handlers are almost always anonymous and call class methods,
//usually to determine if the event needs to be handled by a specific
//instance of the class, or meeting a criteria. e.g.:
if (this.identifier === args.identifier) {
this.someClassMethod(args);
}
}.bind(this));
};
ClassA.prototype.someClassMethod = function (args) {
//handle the event
};
ClassB.js:
var ClassB = function (args) {
//constructor stuff goes here...
};
ClassB.prototype.doAThing = function () {
//code goes here
$(document).trigger('someEvent', { identifier: 'someIdentifier', aValue: 1, anotherValue: 'two' });
};
How/where do I use the #event, #listens, and #fires doclets with this design pattern?