Является ли память неэффективной для создания экземпляров классов в методе получения? Какой OOP дизайн мешает этому? - PullRequest
0 голосов
/ 06 января 2020

У меня есть метод получения, который создает экземпляры классов из десериализованных данных. Я подозреваю, что это ужасно неэффективный способ ведения дел

class Container {
  get content() {
    let contentList = []
    for (let c of this._content) { // this._content is an array of objects
      contentList.push(new ContentTypes[c.type](c)) //ContentTypes is a mapping between type names and classes
    }
    return contentList
  }
}

Каков соответствующий шаблон проектирования на OOP земле?

1 Ответ

2 голосов
/ 06 января 2020

Независимо от того, находится ли код в геттере или методе, эффективность не меняется. Но то, что меняется, - это ожидание от человека, пишущего код с использованием вашего класса.

Я не ожидаю, что доступ к свойству объекта вызовет большие накладные расходы. Поэтому при использовании экземпляра Container, если я вижу свойство contents, я не собираюсь ожидать, что оно выполнит большую работу. Ваш (немного).

Я бы либо:

  1. Сохранял бы копию того, что вы возвращаете (делая то, что вы возвращаете неизменным), и выбрасывайте его только тогда, когда вещи это зависит от изменений, или

  2. Сделайте это методом (явно).

(Или я мог бы сделать оба.)

Я ожидаю, что вызовы методов вызовут больше затрат, чем доступ к свойствам. Я не знаю, существует ли какой-то конкретный c OOP принцип, на который можно ссылаться, но это мой взгляд из опыта (чего бы это ни стоило или не стоило).

Но , обратите внимание, что в дикой природе встречаются контрпримеры. Известным и непосредственно применимым является свойство innerHTML элементов DOM, которое является свойством аксессора, которое выполняет большую часть работы при его использовании.

Вот пример возврата неизменяемой вещи, которую вы сохраняете, и повторно вернуть, но сделать недействительным при изменении базовых данных:

class Container {
    constructor() {
        this._content = [];
        this._exposedContent = null;
    }

    addContent(content) {
        this._content.push(content);
        this._exposedContent = null; // Invalidating the cached copy if any
    }

    get content() {
        // Do we have a cached copy?
        if (!this._exposedContent) {
            // No, create it
            this._exposedContent = this._content.map(
                c => Object.freeze(new ContentTypes[c.type](c))
            );
        }
        return this._exposedContent;
    }
}

(Вы также можете истечь срок действия копии через некоторое время.)

Но это суждение, стоит ли оно того накладные расходы и сложность памяти в сравнении с тем, что на самом деле ваш код в вашем content аксессоре. Моя позиция по умолчанию будет использовать вместо этого метод (getContent или аналогичный), а не кеш, но это суждение.

...