In a project for fun/practice, I made a few builder classes that all started to feel the same, so I decided to generalize them by creating a factory that would automatically assign the similarities that they all shared.Each of my builders had a private variable, data, which would eventually become the built class.Each builder had a reset method that would clear the data object.And each builder had a create method that would return the data object and call the reset method so that the builder could then be used again (they're kind of more like some breed of assembly line, mixing qualities from both builders and factories at this point).Here's my generalized factory for making the builders:function createBuilder(settersMap) {  var data = {};  return Object.keys(settersMap).reduce(function(builder, name) {    builder[name] = function() {      settersMap[name].apply(data, arguments);    }    return builder;  }, {    reset: function() { // so users can clear the builder      data = {};    },    create: function() {      var created = data;      data = {};      return created;    }  });}I use the factory to create driverBuilder and a carBuilder like so:// Driversvar driverBuilder = createBuilder({  setName: function(first, last) {    this.name = first +   + last;  },  setAge: function(age) {    this.age = age;  },  setSkillLevel: function(skillLevel) {    this.skillLevel = skillLevel;  }});var drivers = [];driverBuilder.setName(Joe, McMullen);driverBuilder.setAge(26);driverBuilder.setSkillLevel(6);drivers.push(driverBuilder.create());// Carsvar carBuilder = createBuilder({  setMake: function(make) {    this.make = make;  },  setModel: function(model) {    this.model = model;  },  setTopSpeed: function(topSpeed) {    this.topSpeed = this.topSpeed === undefined ? topSpeed : this.topSpeed + topSpeed;  },  addTurboBoost: function(boost) {    this.topSpeed = this.topSpeed === undefined ? boost : this.topSpeed + boost;  }});var cars = [];carBuilder.setMake(Volkswagen);carBuilder.setModel(Beetle);carBuilder.setTopSpeed(150);carBuilder.addTurboBoost(30);cars.push(carBuilder.create());I then spent the next billion years programming up a gui using jquery which you can mess around with if you'd like to check it out:var RacingLeague = (function() {  // Utility  function createBuilder(settersMap) {    var data = {};    return Object.keys(settersMap).reduce(function(builder, name) {      builder[name] = function() {        settersMap[name].apply(data, arguments);      }      return builder;    }, {      reset: function() {        data = {};      },      create: function() {        var created = data;        data = {};        return created;      }    });  }  // Drivers  var driverBuilder = createBuilder({    setName: function(first, last) {      this.name = first +   + last;    },    setAge: function(age) {      this.age = age;    },    setSkillLevel: function(skillLevel) {      this.skillLevel = skillLevel;    }  });  var drivers = [];  driverBuilder.setName(Joe, McMullen);  driverBuilder.setAge(26);  driverBuilder.setSkillLevel(6);  drivers.push(driverBuilder.create());  driverBuilder.setName(Sam, Benito);  driverBuilder.setAge(21);  driverBuilder.setSkillLevel(3);  drivers.push(driverBuilder.create());  driverBuilder.setName(David Jorgensen); // whoops!  driverBuilder.reset();  driverBuilder.setName(David, Jorgensen);  driverBuilder.setSkillLevel(5);  drivers.push(driverBuilder.create());  // Cars  var carBuilder = createBuilder({    setMake: function(make) {      this.make = make;    },    setModel: function(model) {      this.model = model;    },    setTopSpeed: function(topSpeed) {      this.topSpeed = this.topSpeed === undefined ? topSpeed : this.topSpeed + topSpeed;    },    addTurboBoost: function(boost) {      this.topSpeed = this.topSpeed === undefined ? boost : this.topSpeed + boost;    }  });  var cars = [];  carBuilder.setMake(Volkswagen);  carBuilder.setModel(Beetle);  carBuilder.setTopSpeed(150);  carBuilder.addTurboBoost(30);  cars.push(carBuilder.create());  carBuilder.setMake(Dodge);  carBuilder.setModel(Charger);  carBuilder.setTopSpeed(190);  cars.push(carBuilder.create());  carBuilder.setMake(Pontiac);  carBuilder.setModel(Firebird);  carBuilder.setTopSpeed(180);  carBuilder.addTurboBoost(20);  cars.push(carBuilder.create());  return {    cars: cars,    drivers: drivers,    determineWinner: function(pair1, pair2) {      var odds = 0.5;      odds += pair1.driver.skillLevel > pair2.driver.skillLevel ? 0.15 : 0.00;      odds -= pair1.driver.skillLevel < pair2.driver.skillLevel ? 0.15 : 0.00;      odds += pair1.car.topSpeed > pair2.car.topSpeed ? 0.15 : 0.00;      odds -= pair1.car.topSpeed < pair2.car.topSpeed ? 0.15 : 0.00;      return Math.random() <= odds ? pair1 : pair2;    }  };})();// DOCUMENT READY$(document).ready(function() {  function getDriverId(driver) {    return driver.name;  }  function getDriver(driverId) {    return RacingLeague.drivers.find(function(driver) {      return driver.name === driverId;    });  }  function getCarId(car) {    return `${car.make} ${car.model}`;  }  function getCar(carId) {    carId = carId.split( );    return RacingLeague.cars.find(function(car) {      return car.make === carId[0] && car.model === carId[1];    });  }  var winsMap = {};  RacingLeague.drivers.map(getDriverId).forEach(function(driverId) {    winsMap[driverId] = 0    $(#score-board).append($(`<span>${driverId} Wins: <span id=${driverId}></span></span><br>`));  });  RacingLeague.cars.map(getCarId).forEach(function(carId) {    winsMap[carId] = 0    $(#score-board).append($(`<br><span>${carId} Wins: <span id=${carId}></span></span>`));  });  function refreshWins(winners) {    if (winners) {      winsMap[getDriverId(winners.driver)]++;      winsMap[getCarId(winners.car)]++;    }    Object.keys(winsMap).forEach(function(key) {      $(`[id='${key}']`).html(winsMap[key]);    });  }  refreshWins();  (function addSelectOptions() {    RacingLeague.drivers.map(getDriverId).forEach(function(driverId) {      $('.select-driver').each(function() {        $(this).append($(<option></option>)          .attr(value, driverId)          .text(driverId));      });    });    RacingLeague.cars.map(getCarId).forEach(function(carId) {      $('.select-car').each(function() {        $(this).append($(<option></option>)          .attr(value, carId)          .text(carId));      });    });  })();  function declareWinner(obj) {    refreshWins(obj);    $(#winner-output).html(`${obj.driver.name} in the ${obj.car.make} ${obj.car.model}`);  }  $(#race-button).click(function() {    declareWinner(RacingLeague.determineWinner({      driver: getDriver($(#driver1).val()),      car: getCar($(#car1).val())    }, {      driver: getDriver($(#driver2).val()),      car: getCar($(#car2).val())    }));  });});<script src=https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js></script><body>  <div id=score-board>  </div>  <hr>  <div id=select-racers>    <select class=select-driver id=driver1>    </select>    in the    <select class=select-car id=car1>    </select>    <p>VS</p>    <select class=select-driver id=driver2>    </select>    in the    <select class=select-car id=car2>    </select>  </div>  <br>  <button id=race-button>Race!</button>  <br>  <br>  <span>The winner is: </span><span id=winner-output></span></body>If you have any suggestions for code included in the snippet, I would sincerely appreciate it--I'm not the best front end developer; however, I am quite interested in improving my createBuilder factory method and in hearing discussion involving its pros, cons, and alternatives as well.a jsfiddle link to the projectmy question was somewhat inspired by this one
Factory that Creates Reusable Class Builders for a Racing App
javascript;jquery;factory method
This looks good, except that by resetting the builder, you are throwing away the parameters that you need to build your objects. Yet, parametric construction of objects is the main objective of the Builder design pattern.