You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
constnet=require('net');consthttp=require('http');// Abstract Product ClassclassApiRequest{makeGetRequest(url){returnError(`Implement make Get Request for ${url}`);}}// Product AclasstcpApiRequestextendsApiRequest{makeGetRequest(url){// Handling simple get request without query paramsreturnnewPromise((resolve,reject)=>{constsocket=net.createConnection({host: "www.example.com",port: "80"});socket.on('data',(data)=>resolve(data.toString()));socket.on('error',err=>reject(err));socket.end(`GET / HTTP/1.1\r\nHost: ${url}\r\n\r\n`);});}}// Product BclasshttpApiRequestextendsApiRequest{makeGetRequest(url){// Handling simple get request without query paramsreturnnewPromise((resolve,reject)=>{http.request(`http://${url}`,(res)=>{res.on('data',data=>resolve(data.toString()));res.on('error',err=>reject(err));}).end();});}}/** * This is an abstract factory interface. Uses a static function to * generate family of products. */classApiRequestFactory{staticcreateApiRequest(kind){// This can easily be extended to include HTTPS, HTTP2, HTTP3switch(kind){case"tcp":
returnnewtcpApiRequest();case"http":
returnnewhttpApiRequest();}}}/** * Use this in another class making the product class * and client class isolated */constavailableOptions=["tcp","http"];constapiRequest=ApiRequestFactory.createApiRequest(availableOptions[Math.floor(Math.random()*2)]);apiRequest.makeGetRequest("example.com").then(response=>console.log(response)).catch(err=>console.log(err));
Builder
builder.js
constnet=require('net');/** * This is general Outline on a basic Server */classServer{setHostname(){}setPortNumer(){}setOnConnection(){}listen(){}}/** * Server Builder is implementing the server * using the net. New builder can easily be made to * use server like exrpess etc */classServerBuilderextendsServer{constructor(){super();this._server=null;this._hostname="localhost";this._port=8080;this._isHalfOpenedSockedAllowed=false;this._isPauseOnConnect=false;this._onConnectionCb=()=>{};}setHostname(hostname){this._hostname=hostname;returnthis;}setPortNumer(port){this._port=port;returnthis;}setOnConnection(callback){this._onConnectionCb=callback;returnthis;}setHalfOpenSocketAllowed(){this._isHalfOpenedSockedAllowed=true;returnthis;}setPauseOnConnect(){this._isPauseOnConnect=true;returnthis;}listen(callback){this._server=net.createServer({allowHalfOpen: this._isHalfOpenedSockedAllowed,pauseOnConnect: this._isPauseOnConnect});this._server.on('connection',this._onConnectionCb);this._server.listen(this._port,this._hostname,callback);returnthis;}}// Director class will receive this builder classletserverBuilder=newServerBuilder();// Director class can build server like with builder objectserverBuilder.setHostname("localhost").setPortNumer(8080).listen(()=>console.log("server Started"));
Factory Method
factoryMethod.js
constnet=require('net');consthttp=require('http');// Abstract Product ClassclassApiRequest{makeGetRequest(url){returnError(`Implement make Get Request for ${url}`);}}// Product AclasstcpApiRequestextendsApiRequest{makeGetRequest(url){// Handling simple get request without query paramsreturnnewPromise((resolve,reject)=>{console.log("using tcp Request");constsocket=net.createConnection({host: "www.example.com",port: "80"});socket.on('data',(data)=>resolve(data.toString()));socket.on('error',err=>reject(err));socket.end(`GET / HTTP/1.1\r\nHost: ${url}\r\n\r\n`);});}}// Product BclasshttpApiRequestextendsApiRequest{makeGetRequest(url){// Handling simple get request without query paramsreturnnewPromise((resolve,reject)=>{console.log("using http Request");http.request(`http://${url}`,(res)=>{res.on('data',data=>resolve(data.toString()));res.on('error',err=>reject(err));}).end();});}}// This is the class that would be using the ProductclassClientTcp{main(){/** * Client/Director class is not directly making an object * It uses a class function for doing it */constapiRequest=this.makeGetRequest();apiRequest.makeGetRequest("example.com").then(respone=>console.log(respone)).catch(err=>console.log(err));}// Factory methodmakeGetRequest(){returnnewtcpApiRequest();}}classClientHTTPextendsClientTcp{// Overriding factory method to use different objectmakeGetRequest(){returnnewhttpApiRequest();}}letc=newClientHTTP();c.main();
Prototype
prototype.js
classServer{constructor(port){this._port=port;}listen(){console.log("Listening on port");}clone(){returnnewServer(this._port);}}constserver=newServer();constnewServer=server.clone();newServer.listen();
Singleton
singleton.js
classServer{constructor(port){this._port=port;}staticinit(port){if(typeofServer.instance==='object'){returnServer.instance;}Server.instance=newServer(port);returnServer.instance;}staticgetInstance(){if(typeofServer.instance==='object'){returnServer.instance;}Server.instance=newServer(8080);returnServer.instance;}status(){console.log("Server listening on port "+this._port);}}/** * Client calls init, and getInstance would give that instance * always. Singleton is used for heavy single use objects like DB */Server.init(1234);Server.getInstance().status();
Structural
Adapter
adapter.js
// fs is the adaptee classconstfs=require('fs');// delegator classclassfsDelegator{read(){returnnewError("Please implement read method!");}}/** * Adapter class implements the delegate * Converts fs callbacks to fs promisified */classfsAdapterextendsfsDelegator{read(path){returnnewPromise((resolve,reject)=>{// eslint-disable-next-line node/prefer-promises/fsfs.readFile(__dirname+"/"+path,(err,buf)=>{if(err){returnreject(err);}resolve(buf.toString());});});}}classClient{constructor(){this.setDelegate();}asyncreader(){returnthis._fsDelegate.read("adapter.js");}setDelegate(){this._fsDelegate=newfsAdapter();}}constclient=newClient();client.reader().then(res=>console.log("Reading "+res));
Bridge
bridge.js
/** * ApiRequestFactory gives underlying implementation of * api get request that we make */constApiRequestFactory=require("./lib");classUpstreamFile{getFileUpstream(){}}/** * This is abstraction class that doesnt care about * the implementation of api request. */classConfigextendsUpstreamFile{constructor(url,apiRequest){super();this.url=url;this.apiRequest=apiRequest;}getFileUpstream(){this.apiRequest.makeGetRequest(this.url).then(response=>console.log(response)).catch(err=>console.log(err));}}classPostextendsUpstreamFile{constructor(url,apiRequest){super();this.url=url;this.apiRequest=apiRequest;}getFileUpstream(){this.apiRequest.makeGetRequest(this.url).then(response=>console.log(response)).catch(err=>console.log(err));}}/** * AbstractFactory is used to generate related implementation for these * classes */newConfig("https://jsonplaceholder.typicode.com/todos/1",ApiRequestFactory.createApiRequest("tcp")).getFileUpstream();newPost("jsonplaceholder.typicode.com/posts/1",ApiRequestFactory.createApiRequest("http")).getFileUpstream();
Composite
composite.js
classContentBuffer{getSize(){}}// Composite Class has children as filebufferclassDirBufferextendsContentBuffer{constructor(){super();this.bufferList=[];}getSize(){returnthis.bufferList.map(buf=>buf.getSize()).reduce((a,b)=>a+b);}addBuffer(buf){this.bufferList.push(buf);}}// Leaf classclassFileBufferextendsContentBuffer{setBuffer(buf){this.buf=buf;returnthis;}getSize(){returnthis.buf.length||0;}}constfile1=newFileBuffer().setBuffer(Buffer.from("hello"));constfile2=newFileBuffer().setBuffer(Buffer.from("hello2"));constcompositeObj=newDirBuffer();compositeObj.addBuffer(file1);compositeObj.addBuffer(file2);console.log(compositeObj.getSize());
Decorator
decorator.js
/** * Abtract component */classLogger{log(){}}classBasicLoggerextendsLogger{log(msg){console.log(msg);}}// Decorator class 1classDateDecoratorextendsLogger{constructor(logger){super();this._logger=logger;}log(msg){msg="["+newDate()+"] "+msg;this._logger.log(msg);}}// Decorator class 2classColorDecoratorextendsLogger{constructor(logger){super();this._logger=logger;this.color="\x1b[40m";}log(msg){msg="\x1b[36m"+msg+"\x1b[0m";this._logger.log(msg);}}/** * Enhancing logger via decoratoe */constbasicLogger=newBasicLogger();constcolorDecorator=newColorDecorator(basicLogger);constdateDectorator=newDateDecorator(colorDecorator);dateDectorator.log("Hello World");
Facade
facade.js
constApiRequestFactory=require("./lib");classConfigFormatConvert{staticconvert(config){returnJSON.parse(config);}}classConfigCheck{staticconfigCheck(config){if(!config.body){returnnewError("biy doesnt exist");}returnconfig;}}/** * Config facade handles all config subsystem * Fetching converting then sanitizing */classConfigFacade{staticasyncgetConfig(){letconfig=awaitApiRequestFactory.createApiRequest("http").makeGetRequest('jsonplaceholder.typicode.com/posts/1');config=ConfigFormatConvert.convert(config);config=ConfigCheck.configCheck(config);console.log(config);}}ConfigFacade.getConfig();
Flyweight
flyweight.js
/** * Custom error class. * We shouldnt create new class everytime we encounter * any error */classCustomErrorextendsError{constructor(code,errorMsg){super(errorMsg);this.code=code;this.message=errorMsg;}}/** * Returns the error associated with the code * Reduces the number of objects in the system */classCustomErrorFactor{constructor(){this.errorClasses={};}staticgetInstance(){if(typeofCustomErrorFactor.instace==='object'){returnCustomErrorFactor.instace;}CustomErrorFactor.instace=newCustomErrorFactor();returnCustomErrorFactor.instace;}getErrorClass(code,msg){if(typeofthis.errorClasses[code]==='object'){returnthis.errorClasses[code];}this.errorClasses[code]=newCustomError(code,msg);returnthis.errorClasses[code];}}console.log(CustomErrorFactor.getInstance().getErrorClass(1,"error1").message);console.log(CustomErrorFactor.getInstance().getErrorClass(2,"error2").message);
Proxy
proxy.js
classDatabaseBase{query(){}}classDatabaseextendsDatabaseBase{query(query){return"response"+query;}}// Cached DB objeclassCachedDatabaseextendsDatabaseBase{constructor(){super();this.cacheQuery={};}query(query){if(this.cacheQuery[query]){returnthis.cacheQuery[query];}this.cacheQuery[query]=this.getDatabase().query("quer1");returnthis.cacheQuery[query];}// Lazy initiallization of heavy obejctgetDatabase(){if(typeofthis._database==='object')returnthis._database;this._database=newDatabase();returnthis._database;}}/** * CachedDatabase is proxy object for original db * Lazy initialization * Access control */constdb=newCachedDatabase();console.log(db.query("query1"));
Behavioral
Chain Of Responsibility
chainOfResponsibility.js
classConfigCheck{check(){returntrue;}setNext(next){// Returning a handler from here will let us link handlers in a convenientthis._next=next;returnnext;}}// Chanin of commands for checking configclassAuthCheckextendsConfigCheck{check(config){if(!config.key)returnnewError("No key");if(!config.password)returnnewError("No password");if(this._next)returnthis._next.check(config);else{returnsuper.check();}}}classURLCheckextendsConfigCheck{check(config){if(!config.url)returnnewError("No valid URL");if(this._next)returnthis._next.check(config);else{returnsuper.check();}}}consturlChecker=newURLCheck();constauthChecker=newAuthCheck();urlChecker.setNext(authChecker);console.log(urlChecker.check({}));constconfig={key: "abc",password: "secret",url: "valid url"};console.log(urlChecker.check(config));
Command
command.js
classCommand{execute(){returnnewError("Implement execute method!");}}/** * Simple Stream workflow */classStream{constructor(){this._handlers={};}on(key,command){this._handlers[key]=command;}connect(){// On sftream connectif(this._handlers['connect']){this._handlers['connect'].execute();}// Do some other work // disconnect the connection and call callbackif(this._handlers['disconnect']){this._handlers['disconnect'].execute();}}}// A command implementationclassConnectCallbackextendsCommand{execute(){console.log("executing connect callback");}}classDisconnectCallbackextendsCommand{execute(){console.log("executing disconnect callback");}}constexampleStream=newStream();exampleStream.on('connect',newConnectCallback());exampleStream.on('disconnect',newDisconnectCallback());exampleStream.connect();
Iterator
iterator.js
constfs=require('fs');classIterator{getNext(){}hasNext(){}}// Internally maintains list of files in the folderclassFileBufferIteratorextendsIterator{constructor(folderPath){super();this.folderPath=folderPath;this.currentPosition=0;this.init();}init(){constfolderPath=this.folderPath;letfileList=fs.readdirSync(folderPath);console.log(fileList);fileList=fileList.map(fileName=>folderPath+"/"+fileName);this.fileBuffer=fileList.map(filePath=>fs.readFileSync(filePath));}getNext(){if(this.hasNext()){returnthis.fileBuffer[this.currentPosition++];}}hasNext(){returnthis.fileBuffer.length>this.currentPosition;}}functiontotalSize(iterator){letsize=0;while(iterator.hasNext()){size+=iterator.getNext().length;}returnsize;}console.log(totalSize(newFileBufferIterator(__dirname)));
Mediator
mediator.js
constcluster=require('cluster');if(cluster.isMaster){// Mediate between master class and forksclassMasterProcessMediator{constructor(){this.forks=[];}init(){constworker=cluster.fork();this.forks.push(worker);// worker.on('message',(()=>(message)=>this.handleMessageFromWorker(worker.id,message))());}// handler for various workershandleMessageFromWorker(workerId,message){console.log("Worker "+workerId+" says hi with msg "+message);}notifyAllWorker(){this.forks.map(fork=>fork.send("received Msg"));}}constmediator=newMasterProcessMediator();mediator.init();mediator.notifyAllWorker();}else{process.on('message',(message)=>{console.log(cluster.worker.id+" "+message);});process.send("working");setTimeout(()=>process.kill(process.pid),0);}
Memento
memento.js
// Save board positionclassMemento{constructor(state){this.state=state;}getState(){returnthis.state;}}classTicTacToeBoard{constructor(state=['','','','','','','','','']){this.state=state;}printFormattedBoard(){letformattedString='';this.state.forEach((cell,index)=>{formattedString+=cell ? ` ${cell} |` : ' |';if((index+1)%3==0){formattedString=formattedString.slice(0,-1);if(index<8)formattedString+='\n\u2015\u2015\u2015 \u2015\u2015\u2015 \u2015\u2015\u2015\n';}});console.log(formattedString);}insert(symbol,position){if(position>8||this.state[position])returnfalse;//Cell is either occupied or does not existthis.state[position]=symbol;returntrue;}createMemento(){returnnewMemento(this.state.slice());}setMemento(memnto){this.state=memnto.getState();}}constboard=newTicTacToeBoard(['x','o','','x','o','','o','','x']);board.printFormattedBoard();constcheckpoints=[];checkpoints.push(board.createMemento());board.insert('o',2);board.printFormattedBoard();// Undo previous moveboard.setMemento(checkpoints.pop());board.printFormattedBoard();
Observer
observer.js
constfs=require('fs');// Manages a Subject interactions with observerclassSubjectManager{constructor(){this._observers={};}addObserver(eventType,observer){if(!this._observers[eventType]){this._observers[eventType]=[];}this._observers[eventType].push(observer);}removeObserver(eventType,observer){constidx=this._observers[eventType].indexOf(observer);if(idx>-1){this._observers[eventType].splice(idx);}}notify(eventType,data){this._observers[eventType].forEach(observer=>observer.update(data));}}classFileManager{constructor(){this.subjectManager=newSubjectManager();}monitorFile(path){// eslint-disable-next-line node/no-unsupported-features/es-syntaxfs.watch(path,(data)=>this.subjectManager.notify("change",{path, data}));}addObserver(eventType,observer){this.subjectManager.addObserver(eventType,observer);}removeObserver(eventType,observer){this.subjectManager.removeObserver(eventType,observer);}}classLoggingObserver{update({ data }){console.log(data);}}classSizeChangeObserver{constructor(){this.size=0;}update({ path }){constnewSize=fs.statSync(path).size;if(newSize>this.size){console.log("size increase to "+newSize);this.size=newSize;}}}// Subject classconstfileManager=newFileManager();// Adding observersfileManager.addObserver("change",newLoggingObserver());fileManager.addObserver("change",newSizeChangeObserver());fileManager.monitorFile(process.argv[1]);
State
state.js
constnet=require('net');// Socket Object// Internal State depends on underlying tcp connection// Can be readt connect error, closeclassSocket{constructor(){this.state=newReadyState(this);}connect(url){this.state.connect(url);}setState(state){this.state=state;}printState(){console.log("State is ",this.state);}}classState{connect(){}}classReadyStateextendsState{constructor(socket){super();this.socket=socket;}connect(url){constconnection=net.createConnection({host: url,port: "80"});connection.on('error',()=>this.socket.setState(newErrorState(this.socket)));connection.on('connect',()=>this.socket.setState(newConnectState(this.socket)));connection.on('close',()=>this.socket.setState(newCloseState(this.socket)));}}classErrorStateextendsState{constructor(socket){super();this.socket=socket;}connect(){console.log("cannot connect in error state");}}classConnectStateextendsState{constructor(socket){super();this.socket=socket;}}classCloseStateextendsState{constructor(socket){super();this.socket=socket;}}constsocket=newSocket();consturl="www.example.com";socket.connect(url);socket.printState();// After some time state changes to conenctsetTimeout(()=>socket.printState(),1000);
Strategy
strategy.js
/** * ApiRequestFactory gives underlying startegies for Ali request */constApiRequestFactory=require("./lib");classUpstreamFile{getFileUpstream(){}}/** * Here by default Stategy for API request is http */classConfigextendsUpstreamFile{constructor(url,apiRequest){super();this.url=url;this.apiRequest=apiRequest||ApiRequestFactory.createApiRequest("http");}getFileUpstream(){this.apiRequest.makeGetRequest(this.url).then(response=>console.log(response)).catch(err=>console.log(err));}}/** * AbstractFactory is used to generate related implementation for these * classes */constconfig=newConfig("jsonplaceholder.typicode.com/posts/1");// Using default config httpconfig.getFileUpstream();constconfig2=newConfig("https://jsonplaceholder.typicode.com/todos/1",ApiRequestFactory.createApiRequest("tcp"));// Get tcp strategyconfig2.getFileUpstream();
Template Method
templateMethod.js
// Base template class which computes from bufferclassDataBuffer{constructor(data){this.data=data;}sanitize(data){returndata;}checkForErrors(){returnfalse;}compute(){// Hook to check for errorsconstisError=this.checkForErrors(this.data);if(isError){return-1;}// Hook to sanitize bufferconstsantizeBuffer=this.sanitize(this.data);returnsantizeBuffer.byteLength;}}classWordBufferextendsDataBuffer{constructor(data){super(data);}// Gets only first wordsanitize(data){returnBuffer.from(data.toString().split(" ")[0]);}}constgeneralBuffer=newDataBuffer(Buffer.from('abc def'));console.log(generalBuffer.compute());// Uses Sanitize hook to remove all other wordsconstwordBuffer=newWordBuffer(Buffer.from('abc def'));console.log(wordBuffer.compute());
Visitor
visitor.js
classContentBuffer{getSize(){}}// Composite Class has children as filebufferclassDirBufferextendsContentBuffer{constructor(){super();this.bufferList=[];}getSize(){returnthis.bufferList.map(buf=>buf.getSize()).reduce((a,b)=>a+b);}addBuffer(buf){this.bufferList.push(buf);}accept(visitor){this.bufferList.map(buf=>buf.accept(visitor));returnvisitor.visitDirBuffer(this);}}// Leaf classclassFileBufferextendsContentBuffer{setBuffer(buf){this.buf=buf;returnthis;}getSize(){returnthis.buf.length||0;}accept(visitor){visitor.visitFileBuffer(this);}}// Implement all the alogorithm in visitorclassByteCodeVisitor{constructor(){this.accumlate=0;}visitDirBuffer(){returnthis.accumlate;}visitFileBuffer(fileBuffer){this.accumlate+=fileBuffer.buf.byteLength;}}constfile1=newFileBuffer().setBuffer(Buffer.from("hello"));constfile2=newFileBuffer().setBuffer(Buffer.from("hello2"));constcompositeObj=newDirBuffer();compositeObj.addBuffer(file1);compositeObj.addBuffer(file2);console.log(compositeObj.getSize());constvisitor=newByteCodeVisitor();console.log(compositeObj.accept(visitor));