中心化数据模块 只能在set的时候修改 get的时候获取 不允许外部访问修改的实现方法有哪些

66 阅读3分钟

为了实现一个中心化数据模块,确保数据只能通过特定的set方法来修改,get方法只用于获取数据,且不允许外部直接访问和修改数据,你可以考虑使用以下几种方法。这些方法主要依赖于封装(Encapsulation)私有化数据的概念,确保数据不能被外部直接访问或修改。

1. 使用闭包(Closure)

JavaScript 中可以使用闭包来实现数据的私有化,确保数据只能通过模块内部的 setget 方法访问。外部无法直接修改数据。

const DataModule = (function() {
  let data = {};  // 私有变量,外部无法直接访问

  return {
    set(key, value) {
      data[key] = value;  // 通过 set 方法修改数据
    },
    get(key) {
      return data[key];   // 通过 get 方法获取数据
    }
  };
})();

// 使用
DataModule.set('name', 'John');
console.log(DataModule.get('name')); // John
console.log(DataModule.data);        // undefined, 无法直接访问数据

javascript

特点:

  • 数据保存在闭包内,外部无法直接访问。
  • 只能通过提供的 set 和 get 方法操作数据。

2. 使用 ProxyReflect

你可以使用 JavaScript 的 Proxy 对象来拦截对数据对象的访问,并限制修改操作,仅允许通过 set 方法进行修改。

const data = {};

const DataModule = new Proxy(data, {
  set(target, key, value) {
    if (key === 'set') {
      throw new Error('Use the set method to modify data');
    }
    target[key] = value;
    return true;
  },
  get(target, key) {
    return target[key];
  }
});

const DataController = {
  set(key, value) {
    DataModule[key] = value;
  },
  get(key) {
    return DataModule[key];
  }
};

// 使用
DataController.set('name', 'Alice');
console.log(DataController.get('name')); // Alice
DataController.name = 'Bob';  // 抛出错误:Use the set method to modify data

javascript

特点:

  • 通过 Proxy 拦截外部直接修改操作。
  • 只能通过 set 方法进行修改,直接对 DataModule 修改会抛出错误。

3. 使用 ES6 class# 私有属性

在现代 JavaScript 中,类的私有属性可以通过 # 前缀定义。这使得属性只能在类的内部访问,外部无法访问或修改私有属性。

class DataModule {
  #data = {};  // 私有属性,外部无法访问

  set(key, value) {
    this.#data[key] = value;  // 通过 set 方法修改数据
  }

  get(key) {
    return this.#data[key];   // 通过 get 方法获取数据
  }
}

// 使用
const moduleInstance = new DataModule();
moduleInstance.set('age', 30);
console.log(moduleInstance.get('age'));  // 30
console.log(moduleInstance.#data);       // 抛出错误,外部无法访问 #data

javascript

特点:

  • 通过类的 # 私有属性实现数据封装。
  • 私有属性只能在类内部访问,外部无法直接访问和修改。

4. 使用 TypeScript 或 JavaScript Symbol 实现私有化

如果你使用 TypeScript 或 JavaScript 中的 Symbol 作为私有键,可以隐藏模块中的私有数据。

const _data = Symbol('data');

class DataModule {
  constructor() {
    this[_data] = {};  // 私有数据
  }

  set(key, value) {
    this[_data][key] = value;
  }

  get(key) {
    return this[_data][key];
  }
}

// 使用
const moduleInstance = new DataModule();
moduleInstance.set('location', 'New York');
console.log(moduleInstance.get('location')); // New York
console.log(moduleInstance[_data]);          // undefined, Symbol 属性无法被直接访问

javascript

特点:

  • 通过 Symbol 使得私有属性无法被外部直接访问或修改。
  • 这种方法可以在 ES5/ES6 环境中使用,无需类的私有字段。

5. 使用 Object.freeze() 和工厂函数

你可以使用 Object.freeze() 来冻结数据对象,防止外部修改,保证数据对象的不可变性。

function createDataModule() {
  let data = {};

  return Object.freeze({
    set(key, value) {
      data[key] = value;
    },
    get(key) {
      return data[key];
    }
  });
}

// 使用
const dataModule = createDataModule();
dataModule.set('color', 'blue');
console.log(dataModule.get('color')); // blue
dataModule.color = 'red';  // 没有效果,无法修改
console.log(dataModule.get('color')); // 仍为 blue

javascript

特点:

  • 通过 Object.freeze 防止外部对数据对象的修改。
  • 封装的数据结构确保只能通过 set 和 get 操作。

结论

上述方法都可以实现一个中心化的、只能通过 set 修改,get 获取的数据模块,不允许外部直接修改:

  1. 闭包:数据封装在模块内部,外部无法访问。
  2. Proxy:通过代理拦截修改操作。
  3. 类私有属性:使用 # 前缀定义的私有属性无法被外部访问。
  4. Symbol:通过 Symbol 隐藏数据,使其无法通过常规方式访问。
  5. Object.freeze:冻结数据对象,防止直接修改。

这些方法都能保证数据的安全性,具体选用哪种方案取决于你的项目需求和环境。