[转载] 康威的人生游戏与轻量级模式

参考链接: 康威的人生游戏(Python实现)

从功能和技术的角度来看,Conway的“生活游戏”都非常有趣。  

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

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

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

 

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

  

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

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

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

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

  那让我开始考虑将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;

    }

 

  }

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

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

  我看到的保留当前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、付费专栏及课程。

余额充值