acanessa
acanessa

Reputation: 125

Correct way to implement a Factory pattern in JavaScript in the following code

The following code is supposed to abstract a temperature sensor for a project involving Arduino.

I have the Sensor function representing the hardware sensor, a sensorFactory function to create instances of the sensor, and a saveSensor / findSensor function that stores / returns the sensor objects from an array.

var sensors = [];
const Sensor = (sensorId, sensorType, sensorName) =>{
    var temperature;
    let sensor = {
        sensorId,
        sensorType,
        sensorName,
        temperature,
        readTemperature: (temp) => {
            temperature = temp //simulates reading from hardware
        },
        getTemperature: () => {
            console.log(temperature)
        }
    }
    return sensor; 
};
const SensorFactory = () =>({
    createSensor: (sensorId, sensorType, sensorName) => {
        var sensor = {};
        switch(sensorType){
            case "DS18B20":         
                sensor = Sensor(sensorId,sensorType, sensorName);
                saveSensor(sensor);
                return findSensor(sensorId);
                break;
        }
    },
    getSensor: (sensorId) =>{
    if (sensorId){
            return findSensor(sensorId);            
        }
        return sensors;
    }
});
const saveSensor = (sensor) => {
    sensors.push(sensor);
};
const findSensor = (sensorId) => {
    return sensors[sensorId -1];
};
module.exports = SensorFactory;

I have two questions:

  1. Why can't I see the value of the temperature variable when I run the line console.log(JSON.stringify(sensor1))?

    const SensorFactory = require ("./sensor.js");
    var sensorFactory   = SensorFactory();
    sensorFactory.createSensor (1,"DS18B20", "Cryogenic Tank");
    
    var sensor1 = sensorFactory.getSensor(1);
    sensor1.readTemperature(200);
    sensor1.getTemperature(); //prints 200  
    sensor1.readTemperature(100); //prints 100
    sensor1.getTemperature();   
    sensor1.readTemperature(10); //prints 10
    sensor1.getTemperature();
    
    console.log(JSON.stringify(sensor1))
    

Expected:

{"sensorId":1,"sensorType":"DS18B20","sensorName":"Cryogenic Tank", "temperature": 10}

Actual output:

{"sensorId":1,"sensorType":"DS18B20","sensorName":"Cryogenic Tank"}

I believe that temperature (A) in the following block is a private variable so it should not be accessible from outside the object, but shouldn't I be able to see the temperature variable (B) when I run console.log(JSON.stringify(sensor1))?

const Sensor = (sensorId, sensorType, sensorName) =>{
    var temperature; <----A----private. 
    let sensor = {
        sensorId,
        sensorType,
        sensorName,
        temperature, <----B----I should be able to see this, right?
        readTemperature: (temp) => {
            temperature = temp;
            console.log('readTemperature');             
        },
        getTemperature: () => {             
            console.log('getTemperature');
            console.log(temperature);           }
    }
    return sensor;
};
  1. I am very rusty with JS. Can you please help me understand where I am conceptually wrong? How would you modify the code so that it works as expected?

Upvotes: 0

Views: 136

Answers (2)

acanessa
acanessa

Reputation: 125

@Bergi's second comment is the solution to my question. I have also followed his advice and eliminated the sensorFactory function that returns the sensorFactory object. Code is much clear now.

Upvotes: 0

georg
georg

Reputation: 214979

Here's some refactoring into modern Javascript (answers the second question, and, as a side effect, also the first ;)

class Sensor {
    constructor(id, type, name) {
        this.id = id
        this.type = type
        this.name = name
        this.temperature = null
    }

    readTemperature(temp) {
        this.temperature = temp //simulates reading from hardware
    }
}


class SensorSet extends Map {
    add(id, type, name) {
        this.set(id, new Sensor(id, type, name))
        return this.get(id)
    }
}

let sensors = new SensorSet()

sensors.add(1, "DS18B20", "Cryogenic Tank")

let s1 = sensors.get(1)

s1.readTemperature(200)
console.log(s1.temperature)

s1.readTemperature(100)
console.log(s1.temperature)

s1.readTemperature(10)
console.log(s1.temperature)

console.log(JSON.stringify(s1))

Upvotes: 1

Related Questions