【问题标题】:Correct way to implement a Factory pattern in JavaScript in the following code在以下代码中在 JavaScript 中实现工厂模式的正确方法
【发布时间】:2021-04-20 18:09:55
【问题描述】:

以下代码应该为涉及 Arduino 的项目抽象出温度传感器。

我有一个表示硬件传感器的 Sensor 函数,一个用于创建传感器实例的 sensorFactory 函数,以及一个用于存储/返回数组中的传感器对象的 saveSensor / findSensor 函数。

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;

我有两个问题:

  1. 为什么我在运行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))
    

预期:

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

实际输出:

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

我相信以下块中的温度 (A) 是一个私有变量,因此不应从对象外部访问它,但是当我运行 console.log(JSON.stringify(sensor1)) 时,我不应该能够看到温度变量 (B) ?

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. 我对 JS 很生疏。你能帮我理解我在概念上的错误吗?您将如何修改代码以使其按预期工作?

【问题讨论】:

  • 为什么SensorFactory是一个返回工厂对象的函数?似乎所有的工厂都是一样的。只需使用module.exports = {createSensor(…) { … }, getSensor(…) { … }};
  • "为什么我看不到温度变量的值" - 因为JSON.stringify 只打印.temperature 对象属性的值,而不是@987654332 @ 你的 readTemperature 方法分配的局部变量。请改用 getTemperature() 并从对象中删除不可变属性 - 或从代码中删除变量并始终访问该属性。
  • @Bergi 这对我来说是解决方案的重要组成部分。我试图偷懒,看到 readTemperature 在将对象传递给车把模板之前正在更改温度变量的值。我也忘了在getTemperature 方法中添加return temperature 行。我的代码现在按预期工作。当你说“为什么 SensorFactory 是一个返回工厂对象的函数?”时,你能帮我理解你的意思吗?我的想法是让 SensorFactory 返回不同类型的传感器对象。
  • "我的想法是让 SensorFactory 返回不同类型的传感器对象。" - 是的,a SensorFactory 应该这样做,就像具体的sensorFactory 使用其 createSensor 方法。但是为什么你有一个SensorFactory 函数来创建工厂呢?
  • @Bergi:因为我不是程序员,所以有些概念让我很困惑。我明白你现在在问什么,事实上我在另一个模块中遵循你的建议并按照你的建议导出。

标签: javascript optimization scope factory


【解决方案1】:

这是对现代 Javascript 的一些重构(回答了第二个问题,并且,作为副作用,也是第一个问题;)

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))

【讨论】:

  • 谢谢。我应该澄清一下我试图避免使用类。道歉。您如何建议仅使用函数来执行此操作?
  • "避免使用类。" - 为什么?
  • 我曾使用类传递绑定问题,并且我读到我应该更喜欢函数而不是类,即link,而函数组合或继承,即link。你的代码很清晰,是我以前用 PHP 编码的方式,这很有意义。但是,我发现过去使用函数和组合比使用类和继承更容易。我将继续努力并发布我的更新。
  • @acanessa:我明白了。不幸的是,互联网充满了误导,如果不是完全错误的东西(重新链接)。我的建议是坚持任何让你感觉更舒服的东西。祝你的项目好运!
【解决方案2】:

@Bergi 的 第二条评论是我的问题的解决方案。我也听从了他的建议,去掉了返回 sensorFactory 对象的 sensorFactory 函数。代码现在很清晰了。

【讨论】:

    猜你喜欢
    • 2011-07-04
    • 2012-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多