康威生命游戏_康威的人生游戏和轻量级模式

康威生命游戏

轻量级 从功能和技术的角度来看,Conway的“人生游戏”都令人着迷。

这可以解释为什么它经常用于代码撤退 。 代码撤退是一种有趣的学习方法。

几乎每次与新对一起工作都会为您带来新见解,这真是令人惊讶。


在我参加的最后一次代码务虚会上,我的一对建议我们对单元格使用Flyweight模式

flyweight是一个共享对象,可以同时在多个上下文中使用。 在每个上下文中,flyweight都充当一个独立的对象-与未共享的对象实例是无法区分的。

当《 设计模式》一书(包含上面的引文)问世时,我记得有很多啊哈。 看到我以前使用过的所有这些模式,并最终为其命名,真是太酷了,这样我可以与同龄人更有效地讨论它们!

但是,当我阅读有关飞重的信息时,我并没有感到惊讶。 书中的示例在文本编辑器中共享字符对象,当时似乎有些牵强。 但是,此示例与“生命游戏”网格中的单元格并无不同,因此我很高兴地沿用了他们俩的想法,探索了该模式在这种情况下的适用性。

代码撤退结束后,我进一步考虑了该模式。 (这通常是代码撤退真正开始起作用的地方。)

实际上,我们一直在使用潜在的重量级:布尔值。 布尔值是只有两个实例的类,可以轻松共享这些实例。 在Java中,它们不是: new Boolean(true) != new Boolean(true) 。 但是, Boolean类确实为可用于共享的实例提供了两个常量TRUEFALSE

那让我开始考虑将Enum用作飞行重量。 大多数时候,我使用枚举对相关但互斥的常量进行分组,例如一周中的几天。 但是,Java中的Enum可以定义方法:

public enum Cell {

    ALIVE(true), DEAD(false);

    private final boolean alive;

    private Cell(boolean alive) {
      this.alive = alive;
    }

    public boolean isAlive() {
      return alive;
    }

    public Cell evolve(int numLiveNeighbors) {
      boolean aliveInNextGeneration = alive
          ? 2 <= numLiveNeighbors && numLiveNeighbors <= 3
          : numLiveNeighbors == 3;
      return aliveInNextGeneration ? ALIVE : DEAD;
    }

  }

代码撤退的有趣部分之一是,在某些会话中,您将对工作方式有所限制。 这样的限制迫使您更具创造力,并超出了通常使用的技术范围进行思考。

在这种情况下有趣的一个约束是不使用任何条件,例如ifswitch语句或三元运算符。 该约束背后的想法是迫使您用多态替换条件语句 ,从而使程序更加面向对象。

我看到的保留当前Cell枚举而不使用条件的唯一方法是引入映射:

public enum Cell {

    ALIVE(true), DEAD(false);

    private final boolean alive;
    private static final Map<Boolean, Map<Integer, Cell>> 
        NEXT = new HashMap<>();

    static {
      Map<Integer, Cell> dead = new HashMap<>();
      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 = new HashMap<>();
      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);
    }

    private Cell(boolean alive) {
      this.alive = alive;
    }

    public boolean isAlive() {
      return alive;
    }

    public Cell evolve(int numLiveNeighbors) {
      return NEXT.get(alive).get(numLiveNeighbors);
    }

  }

这种方法可行,但不是很优雅,并且随着可能性的增加而失效。 显然,我们需要更好的选择。

摆脱条件的唯一方法是摆脱单元格的布尔状态。 这意味着我们需要为两个实例使用不同的类,以便类型隐式体现状态。 反过来,这意味着我们需要一个工厂来向客户端隐藏这些类:

public interface Cell {

    boolean isAlive();
    Cell evolve(int numLiveNeighbors);

  }

  public class CellFactory {

    private static final Map<Boolean, Cell> CELLS 
        = new HashMap<>();

    static {
      CELLS.put(false, new DeadCell());
      CELLS.put(true, new AliveCell());
    }

    public static Cell dead() {
      return cell(false);
    }

    public static Cell alive() {
      return cell(true);
    }

    static Cell cell(boolean alive) {
      return CELLS.get(alive);
    }

  }

  class DeadCell implements Cell {

    @Override
    public boolean isAlive() {
      return false;
    }

    @Override
    public Cell evolve(int numLiveNeighbors) {
      return CellFactory.cell(numLiveNeighbors == 3);
    }

  }

  class AliveCell implements Cell {

    @Override
    public boolean isAlive() {
      return true;
    }

    @Override
    public Cell evolve(int numLiveNeighbors) {
      return CellFactory.cell(numLiveNeighbors == 2 
          || numLiveNeighbors == 3);
    }

  }

确实,当您查看Flyweight模式时,您会看到建议的结构包含一个flyweight工厂,该工厂创建实现了常见flyweight接口的具体flyweight类的实例。

感谢代码撤退和我的合作伙伴,我现在知道为什么。

翻译自: https://www.javacodegeeks.com/2014/04/conways-game-of-life-and-the-flyweight-pattern.html

康威生命游戏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值