
Это может объяснить, почему это часто используется для отступления кода . Кодовые отступления — интересный способ изучения.
Удивительно, как работа с новыми парами дает вам новые идеи практически каждый раз.
На последнем ретрите кода, который я посетил, одна из моих пар предложила использовать шаблон Flyweight для ячеек:
Flyweight — это общий объект, который может использоваться одновременно в нескольких контекстах. Flyweight действует как независимый объект в каждом контексте — он неотличим от экземпляра объектов, которые не являются общими.
Когда вышла книга Design Patterns (которая содержит приведенную выше цитату), я помню, что у меня было много моментов ага. Было так круто увидеть все эти шаблоны, которые я использовал раньше, и, наконец, назвать их, чтобы я мог обсудить их с коллегами более эффективно!
У меня не было ага, когда я читал о весе в полете, однако. Пример, приведенный в книге о совместном использовании символьных объектов в текстовом редакторе, в то время казался немного надуманным. Однако этот пример мало чем отличается от ячеек в сетке Game of Life, поэтому я с радостью согласился с идеей моей пары исследовать применимость шаблона в этом контексте.
После того, как отступление кода было закончено, я немного подумал над этим шаблоном. (Это обычно, когда отступление кода действительно начинает окупаться.)
 На самом деле мы все время используем потенциальный вес в полете: логические значения.  Логический класс — это класс только с двумя экземплярами, и эти экземпляры могут легко использоваться совместно.  В Java это не так: new Boolean(true) != new Boolean(true) .  Однако Boolean класс предоставляет две константы, TRUE и FALSE , для экземпляров, которые вы можете использовать для совместного использования. 
  Это заставило меня задуматься об использовании Enum s для навесок.  Большую часть времени я использую перечисления для группировки связанных, но взаимоисключающих констант, например, дней недели.  Однако Enum s в Java может определять методы: 
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 | publicenumCell {    ALIVE(true), DEAD(false);    privatefinalbooleanalive;    privateCell(booleanalive) {      this.alive = alive;    }    publicbooleanisAlive() {      returnalive;    }    publicCell evolve(intnumLiveNeighbors) {      booleanaliveInNextGeneration = alive          ? 2<= numLiveNeighbors && numLiveNeighbors <= 3          : numLiveNeighbors == 3;      returnaliveInNextGeneration ? ALIVE : DEAD;    }  } | 
Одна из забавных частей отступлений кода заключается в том, что на некоторых сессиях у вас будут ограничения на работу. Такие ограничения заставляют вас быть более креативными и думать не только о тех методах, которые вы обычно используете.
  Одно ограничение, которое интересно в этом контексте, состоит в том, чтобы не использовать какие-либо условия, такие как операторы if или switch или троичные операторы.  Идея этого ограничения состоит в том, чтобы заставить вас заменить условные выражения полиморфизмом , делая вашу программу более объектно-ориентированной. 
  Единственный способ сохранить текущее перечисление Cell и не использовать условные выражения — это представить карту: 
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | publicenumCell {    ALIVE(true), DEAD(false);    privatefinalbooleanalive;    privatestaticfinalMap<Boolean, Map<Integer, Cell>>         NEXT = newHashMap<>();    static{      Map<Integer, Cell> dead = newHashMap<>();      dead.put(0, DEAD);      dead.put(1, DEAD);      dead.put(2, DEAD);      dead.put(3, ALIVE);      dead.put(4, DEAD);      dead.put(5, DEAD);      dead.put(6, DEAD);      dead.put(7, DEAD);      dead.put(8, DEAD);      dead.put(9, DEAD);      NEXT.put(false, dead);      Map<Integer, Cell> alive = newHashMap<>();      alive.put(0, DEAD);      alive.put(1, DEAD);      alive.put(2, ALIVE);      alive.put(3, ALIVE);      alive.put(4, DEAD);      alive.put(5, DEAD);      alive.put(6, DEAD);      alive.put(7, DEAD);      alive.put(8, DEAD);      alive.put(9, DEAD);      NEXT.put(true, alive);    }    privateCell(booleanalive) {      this.alive = alive;    }    publicbooleanisAlive() {      returnalive;    }    publicCell evolve(intnumLiveNeighbors) {      returnNEXT.get(alive).get(numLiveNeighbors);    }  } | 
Этот подход работает, но он не очень элегантен и ломается, когда число возможностей растет. Очевидно, нам нужна лучшая альтернатива.
Единственный способ избавиться от условного — избавиться от логического состояния ячейки. Это означает, что нам нужно иметь разные классы для двух экземпляров, чтобы тип неявно воплощал состояние. Это, в свою очередь, означает, что нам нужна фабрика, чтобы скрыть эти классы от клиента:
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | publicinterfaceCell {    booleanisAlive();    Cell evolve(intnumLiveNeighbors);  }  publicclassCellFactory {    privatestaticfinalMap<Boolean, Cell> CELLS         = newHashMap<>();    static{      CELLS.put(false, newDeadCell());      CELLS.put(true, newAliveCell());    }    publicstaticCell dead() {      returncell(false);    }    publicstaticCell alive() {      returncell(true);    }    staticCell cell(booleanalive) {      returnCELLS.get(alive);    }  }  classDeadCell implementsCell {    @Override    publicbooleanisAlive() {      returnfalse;    }    @Override    publicCell evolve(intnumLiveNeighbors) {      returnCellFactory.cell(numLiveNeighbors == 3);    }  }  classAliveCell implementsCell {    @Override    publicbooleanisAlive() {      returntrue;    }    @Override    publicCell evolve(intnumLiveNeighbors) {      returnCellFactory.cell(numLiveNeighbors == 2          || numLiveNeighbors == 3);    }  } | 
Действительно, когда вы посмотрите шаблон Flyweight, вы увидите, что предлагаемая структура содержит фабрику flyweight, которая создает экземпляры конкретных классов flyweight, которые реализуют общий интерфейс flyweight.
Благодаря отступлению от кода и моему партнеру я теперь знаю почему.
| Ссылка: | Игра жизни Конвея и шаблон Flyweight от нашего партнера JCG Ремона Синнема в блоге по разработке безопасного программного обеспечения . |