Контакт с вложенным, если тогда еще/вложил операторы переключения

Хотя прокси-сервер будет работать, он также будет работать довольно медленно. Различный подход будет для каждого метода, который должен использовать значение _determinant, сначала пройти через различную функцию , чтобы проверить, нужно ли обновить _determinant (и если да, то обновить ). Таким образом, дорогостоящий пересчет выполняется не каждый раз, когда изменяется массив, а только вовремя для использования результата. Например:

class Matrix extends Array {
  constructor() {
    var args  = [];
    for (var i = 0; i < arguments.length; i++) {
      if (Array.isArray(arguments[i])) {
        args.push(new Matrix(...arguments[i]));
      } else {
        args.push(arguments[i]);
      }
    }
    super(...args);
    this._determinant = null;
  }
  // next method is effectively a recursive deep join
  // could also use toString if it doesn't interfere with anything else
  getString() {
    const itemsStr = this.map((item) => (
    item instanceof Matrix
      ? item.getString()
      : item
    ))
    .join(',');
    const result = '[' + itemsStr + ']';
    return result;
  }
  getDeterm() {
    const newString = this.getString();
    if (newString !== this._lastString) {
      this._lastString = newString;
      this.upperEchelon();
    }
    return this._determinant;
  }
  upperEchelon() {
    console.log('running upperEchelon');
    this._determinant = Math.random();
  }
}

const m = new Matrix([2, 3, 4], 5);
console.log(m.getDeterm());
// Not calculated again:
console.log(m.getDeterm());
// Mutation, next call of getDeterm will run upperEchelon:
m[0][0] = 1;
console.log(m.getDeterm());

11
задан Cherian 30 January 2009 в 04:41
поделиться

7 ответов

Вы хотите использовать рефакторинг, который заменяет условное выражение с помощью полиморфного класса. Например.

Или вот другой пример

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

Править

Позвольте мне добавить, что это не идеальное решение в каждом случае. Как (я забыл Ваше имя извините) указал в моих комментариях, несколько раз это может быть болью особенно, если необходимо создать объектную модель только, чтобы сделать это. Эти экс-ячейки рефакторинга, если у Вас есть это:

function doWork(object x)
{

   if (x is a type of Apple)
   {
      x.Eat();

   } else if (x is a type of Orange)
   {
      x.Peel();
      x.Eat();
   }

}

Здесь можно осуществить рефакторинг переключатель в некоторый новый метод, который обработает каждый фрукт.

Править

Поскольку кто-то указал, как Вы создаете правильный тип для входа в doWork, существует больше способов решить эту проблему затем, я мог прочертовский список так некоторые основные пути. Первым и самым прямым (и да идет вразрез с мелкой частицей этого вопроса) является переключатель:

class FruitFactory
{
   Fruit GetMeMoreFruit(typeOfFruit)
   {
         switch (typeOfFruit)
         ...
         ...
   }
}

Хорошая вещь об этом подходе, это легко записать и обычно является первым методом, который я использую. В то время как у Вас все еще есть оператор переключения его изолированное к одной области кода, и является очень простым все, что это возвращает, объект n. Если у Вас только есть несколько объектов и они; ре, не изменяющее это, работает очень хорошо.

Другие более сложные шаблоны, которые можно изучить, являются Абстрактной Фабрикой. Вы могли также динамично создать Фрукты если Ваша поддержка платформ это. Вы могли также использовать что-то как Шаблон Поставщика. То, которое по существу мне означает, что Вы настраиваете свой объект, и затем у Вас есть фабрика, которую на основе конфигурации и ключа Вы даете фабрике, создает правильный класс динамично.

6
ответ дан 3 December 2019 в 05:36
поделиться

Вы считали это на сглаживающемся коде стрелки от Кодирования Ужаса?

Можно заменить бросок возвратом или goto при использовании языка без исключений.

8
ответ дан 3 December 2019 в 05:36
поделиться

Вы думали о Google "Чистые Переговоры по Коду - Наследование, Полиморфизм, и Тестировали" видео? Это обсуждает подходы к использованию Объектно-ориентированных методов, чтобы удалить если/переключатель условные выражения.

2
ответ дан 3 December 2019 в 05:36
поделиться

Я на самом деле записал о том, как решить, это выходит в моем блоге в апреле 2008. Смотрите здесь и сообщите мне то, что Вы думаете.

Я рекомендую Вам:

  1. Используйте полиморфизм для получения корректного поведения во время выполнения, в котором Вы нуждаетесь без условных операторов.

  2. Возьмите все свои условные операторы и переместите их в своего рода "фабрику", которая вручит Вам соответствующий тип во времени выполнения.

  3. Вы сделаны. Разве это не было легко?:)

Если Вы хотите видеть некоторый фактический пример кода о том, как преобразовывают Ваш код, голова к моему блогу.

P.S. Это не дешевая попытка сам продвижение; я был ТАК пользователь в течение долгого времени теперь, и это - первый раз, когда я связался со своим блогом - и я только сделал поэтому, потому что я думаю, что это релевантно.

3
ответ дан 3 December 2019 в 05:36
поделиться

Вы могли бы хотеть посмотреть на Стратегическую модель, где вместо того, чтобы поместить длинную цепочку IFS со связанными условиями, Вы абстрагируете каждое условие к различному объекту, каждое определение что его определенное поведение.

Класс, который определяет те объекты, реализует Интерфейс, который назовет родительский объект.

1
ответ дан 3 December 2019 в 05:36
поделиться

Вы не говорите, какой язык Вы используете, но если Вы используете язык OO, такой как C++, C# или Java, можно часто использовать виртуальные функции для решения той же проблемы, как Вы в настоящее время решаете с a switch оператор, и более расширяемым способом. В случае C++ сравните:

class X {
public:
    int get_type();     /* Or an enum return type or similar */
    ...
};

void eat(X& x) {
    switch (x.get_type()) {
    TYPE_A: eat_A(x); break;
    TYPE_B: eat_B(x); break;
    TYPE_C: eat_C(x); break;
    }
}

void drink(X& x) {
    switch (x.get_type()) {
    TYPE_A: drink_A(x); break;
    TYPE_B: drink_B(x); break;
    TYPE_C: drink_C(x); break;
    }
}

void be_merry(X& x) {
    switch (x.get_type()) {
    TYPE_A: be_merry_A(x); break;
    TYPE_B: be_merry_B(x); break;
    TYPE_C: be_merry_C(x); break;
    }
}

с

class Base {
    virtual void eat() = 0;
    virtual void drink() = 0;
    virtual void be_merry() = 0;
    ...
};

class A : public Base {
public:
    virtual void eat() { /* Eat A-specific stuff */ }
    virtual void drink() { /* Drink A-specific stuff */ }
    virtual void be_merry() { /* Be merry in an A-specific way */ }
};

class B : public Base {
public:
    virtual void eat() { /* Eat B-specific stuff */ }
    virtual void drink() { /* Drink B-specific stuff */ }
    virtual void be_merry() { /* Be merry in an B-specific way */ }
};

class C : public Base {
public:
    virtual void eat() { /* Eat C-specific stuff */ }
    virtual void drink() { /* Drink C-specific stuff */ }
    virtual void be_merry() { /* Be merry in a C-specific way */ }
};

Преимущество состоит в том, что можно добавить новый Base- производные классы D, E, F и так далее не имея необходимость касаться любого кода, который только имеет дело с указателями или ссылками на Base, таким образом, нет ничего, что может стать устаревшим путь который a switch оператор может в исходном решении. (Преобразование выглядит очень похожим в Java, где методы являются виртуальными по умолчанию, и я уверен, что это выглядит подобным в C# также.) На крупном проекте это - огромная победа пригодности для обслуживания.

1
ответ дан 3 December 2019 в 05:36
поделиться

Как насчет:

/* Code Block 1... */

if(/* result of some condition or function call */)
{
   /* Code Block 2... */

   if(/* result of some condition or function call */)
   {
      /* Code Block 3... */

      if(/* result of some condition or function call */)
      {
         /* Code Block 4... */
      }
   }
}

Становится этим:

/* Code Block 1... */
IsOk = /* result of some condition or function call */

if(IsOK)
{
   /* Code Block 2... */
   IsOk = /* result of some condition or function call */
}

if(IsOK)
{
   /* Code Block 3...*/
   IsOk = /* result of some condition or function call */
}

if(IsOK)
{
   /* Code Block 4...*/
   IsOk = /* result of some condition or function call */
}

/* And so on... */

Можно, конечно, возвратиться, если когда-нибудь IsOk становится ложью, при необходимости.

0
ответ дан 3 December 2019 в 05:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: