Singleton Pattern | Factory Pattern | Constructor Pattern
let instance;
let globalState = {
color: ""
};
class StateUtility {
constructor() {
if (instance) {
throw new Error("New instance cannot be created!!");
}
instance = this;
}
getPropertyByName(propertyName) {
return globalState[propertyName];
}
setPropertyValue(propertyName, propertyValue) {
globalState[propertyName] = propertyValue;
}
}
let stateUtilityInstance = Object.freeze(new StateUtility());
export default stateUtilityInstance;
globalState
. We expose them using the class methods of StateUtility
. In this way, we protect the global state from being altered directly.let stateUtilityInstance = Object.freeze(new StateUtility());
.Object.freeze
so that no other class/component/module is able to modify the exposed stateUtilityInstance
.// creates factory function
function vehicleFactory (manufacturer, plateNO) {
return {
manufacturer,
plateNO,
startEngine () {
console.log("reving engine")
},
drive () {
console.log("driving car...")
}
}
}
const Vehicle1 = vehicleFactory("Toyota", 12345);
console.log(Vehicle1)
// prints
//{
// manufacturer: 'Toyota',
// plateNO: 12345,
// startEngine: [Function: startEngine],
// drive: [Function: drive]
//}
const Vehicle2 = vehicleFactory("Ford", 13345);
console.log(Vehicle2)
// prints
// {
// manufacturer: 'Ford',
// plateNO: 13345,
// startEngine: [Function: startEngine],
// drive: [Function: drive]
// }
Examples,
StartEngine
, driveVehicle
, and stopEngine
methods.class Car {
constructor(options) {
this.wheels = options.wheels || 4;
this.doors = options.doors || 4;
this.color = options.color || "silver";
}
}
class Truck {
constructor(options) {
this.wheels = options.wheels || 6;
this.doors = options.doors || 2;
this.color = options.color || "red";
}
}
class Factory {
create = (options, vehicleType) => {
if(!vehicleType) {
return "unable to make vehicle. Please specify a vehicle type and tryagain!"
}
let vehicle;
if (vehicleType === "car") {
vehicle = new Car(options);
} else if (vehicleType === "truck") {
vehicle = new Truck(options);
}
vehicle.vehicleType = vehicleType;
vehicle.startEngine = ()=> console.log(`Reving ${vehicleType} engine`);
vehicle.driveVehicle = ()=> console.log(`Driving ${vehicleType}...`);
vehicle.stopEngine = ()=> console.log(`Stop ${vehicleType} engine`);
return vehicle;
}
};
const vehicleFactory = new Factory();
const car = vehicleFactory.create({
wheels: 4,
doors: 2,
color: "black",
}, "car");
console.log(car)
console.log(car.startEngine())
console.log(car.driveVehicle())
// prints:
//Car {
// wheels: 4,
// doors: 4,
// color: 'silver',
// vehicleType: 'car',
// startEngine: [Function],
// driveVehicle: [Function],
// stopEngine: [Function]
//}
// Reving car engine
// Driving car...
const truck = vehicleFactory.create({
wheels: 4,
doors: 2,
color: "yellow",
}, "truck")
console.log(truck)
console.log(truck.startEngine())
console.log(truck.stopEngine())
// prints
//Truck {
// wheels: 4,
// doors: 2,
// color: 'yellow',
// vehicleType: 'truck',
// startEngine: [Function],
// driveVehicle: [Function],
// stopEngine: [Function]
//}
// Reving truck engine
// Stop truck engine
class Car {
constructor(options) {
this.wheels = options.wheels || 4;
this.doors = options.doors || 4;
this.color = options.color || "silver";
}
}
class Truck {
constructor(options) {
this.wheels = options.wheels || 6;
this.doors = options.doors || 2;
this.color = options.color || "red";
}
}
class Bus {
constructor(options) {
this.wheels = options.wheels || 4;
this.doors = options.doors || 4;
this.color = options.color || "white";
}
}
class Motorcycle {
constructor(options) {
this.wheels = options.wheels || 2;
this.doors = options.doors || 0;
this.color = options.color || "Black";
}
}
class Factory {
create = (options, vehicleType) => {
if(!vehicleType) {
return "unable to make vehicle. Please specify a vehicle type and tryagain!"
}
let vehicle;
if (vehicleType === "car") {
vehicle = new Car(options);
} else if (vehicleType === "truck") {
vehicle = new Truck(options);
} else if (vehicleType === "bus") {
vehicle = new Bus(options);
} else if (vehicleType === "motorcycle") {
vehicle = new Motocycle(options);
}
vehicle.vehicleType = vehicleType;
vehicle.startEngine = ()=> console.log(`Reving ${vehicleType} engine`);
vehicle.driveVehicle = ()=> console.log(`Driving ${vehicleType}...`);
vehicle.stopEngine = ()=> console.log(`Stop ${vehicleType} engine`);
return vehicle;
}
};
const vehicleFactory = new Factory();
const bus = vehicleFactory.create({
wheels: 4,
doors: 4,
color: "yellow",
}, "bus");
console.log(bus)
console.log(bus.startEngine())
console.log(bus.driveVehicle())
// prints:
// Bus {
// wheels: 4,
// doors: 4,
// color: 'yellow',
// vehicleType: 'bus',
// startEngine: [Function],
// driveVehicle: [Function],
// stopEngine: [Function]
//}
// Reving bus engine
// Driving bus...
const bike = vehicleFactory.create({
wheels: 2,
doors: 0,
color: "red",
}, "motorcycle")
console.log(bike)
console.log(bike.startEngine())
console.log(bike.stopEngine())
// prints
// Motorcycle {
// wheels: 2,
// doors: 0,
// color: 'red',
// vehicleType: 'bike',
// startEngine: [Function],
// driveVehicle: [Function],
// stopEngine: [Function]
//}
// Reving motorcycle engine
// Stop motorcycle engine
More examples,
var Factory = function () {
this.createEmployee = function (type) {
var employee;
if (type === "fulltime") {
employee = new FullTime();
} else if (type === "parttime") {
employee = new PartTime();
} else if (type === "temporary") {
employee = new Temporary();
} else if (type === "contractor") {
employee = new Contractor();
}
employee.type = type;
employee.say = function () {
console.log(this.type + ": rate " + this.hourly + "/hour");
}
return employee;
}
}
var FullTime = function () {
this.hourly = "$12";
};
var PartTime = function () {
this.hourly = "$11";
};
var Temporary = function () {
this.hourly = "$10";
};
var Contractor = function () {
this.hourly = "$15";
};
function run() {
var employees = [];
var factory = new Factory();
employees.push(factory.createEmployee("fulltime"));
employees.push(factory.createEmployee("parttime"));
employees.push(factory.createEmployee("temporary"));
employees.push(factory.createEmployee("contractor"));
for (var i = 0, len = employees.length; i < len; i++) {
employees[i].say();
}
}
const vehicleOptions = {type: "cars", color: "white", doors: 4, wheels: 4}
// factory pattern
function Factory(options) {
let factory = {};
factory.type = options.type;
factory.color = options.color;
factory.wheels = options.wheels;
factory.doors = options.doors;
return factory;
}
const vehicle = Factory(vehicleOptions);
// constructor pattern
function ConstructorPattern(options) {
this.type = options.type;
this.color = options.color
this.doors = options.doors;
this.wheels = options.wheels;
}
const vehicle2 = new ConstructorPattern(vehicleOptions);
console.log("factory car", vehicle)
// prints { type: 'cars', color: 'white', wheels: 4, doors: 4 }
console.log("constructor car", vehicle2)
// prints { type: 'cars', color: 'white', wheels: 4, doors: 4 }
The Factory pattern can be especially useful when applied to the following situations:
Source: Levelup