Java:带有类型单元的细胞自动机

3

我正在开发一个基于Java的元胞自动机实现(不确定它是否严格属于这一类),其中单个细胞可能具有不同类型,封装了不同的数据和CA规则。可能会有大量类型,我希望能够动态地插入新类型,而不必维护其他代码。

所有细胞类型都是从一个公共基类派生而来。每个细胞的更新(update)方法在模拟的每一帧中仅被调用一次:

public abstract class Cell
{
    public abstract void update(Cell[] neighbors);
}

这在 CA 规则只需要有关单元格数据的情况下很好用,例如:
public class CellTypeA extends Cell
{
    public int Data = 0;

    @Override
    public void update(Cell[] neighbors)
    {
        Data++;
    }
}

然而,我有一些模拟规则需要让单元格查询相邻的邻居单元格以获取数据,但仅当它们属于具有该数据的类型时。使用instanceof运算符来实现这一点是很诱人的:

public class CellTypeB extends Cell
{
    public boolean State = false;

    private void update(Cell[] neighbors)
    {
        for (Cell c : neighbors)
        {
            if (c instanceof CellTypeA)
            {
                State = (((CellTypeA)c).getData() > 10);
            }
        } 
    }
}

如果可能的话,我希望避免使用有臭味的 instanceof。我也不能将getData()提升到超类以实现多态性,因为这些单元格的实际数据结构会更加复杂和多样化。我一直在阅读GoF访问者模式,以解决instanceof滥用问题,但似乎无法弄清如何将其应用于此问题。对于如何解决此问题或其他方法的想法如何?

谢谢! 史蒂夫


我明白你所说的交互实际上并不属于任何一个单元格,但如果这样做,我岂不是最终会在一个巨大的switch语句中使用instanceof来定义所有的交互排列组合?而且,一个实现客户端是否需要修改或扩展这个类来定义新的交互呢?或者我理解你的意思有误? - Stephen Carlson
另一个需要注意的是,如果你在一个类中有方法 operate(Cell c)operate(CellSubclass s),并且你调用 operate(x),Java 将会选择最匹配的派生类型的方法。 - sje397
实际上,这取决于您传递的ref类型,因此可能无法帮助 :/ - sje397
是的,你说得对,不是很有用。 :) - Stephen Carlson
1
我可能会保留instanceof检查的形式,可能是隐藏的,并倾向于使用接口而不是具体类型。 "更多模式"并不一定更好,必须权衡复杂性与任何好处。将更新移出每个单元格听起来像是一个值得探索的方法(主要是它允许应用不同的算法而不改变“愚蠢”的单元格数据对象类),但这是一个正交任务。我通常不喜欢访问者模式,而且在这种情况下经常更喜欢手动处理“类型区分”。 - user2864740
显示剩余3条评论
1个回答

2
我玩了一下,无法想象如何使访问者模式 a) 优雅地处理两个要访问的项,并且 b) 像您所需的那样可插拔。
这个方法可以实现,但可能会隐藏在 Guava 中 instanceof 的内容:
import com.google.common.collect.Iterables;
import java.util.Arrays;

public class CellTypeB extends Cell
{
    public boolean State = false;

    @Override
    public void update(Cell[] neighbors) {
        Iterable<CellTypeA> onlyAs = Iterables.filter(Arrays.asList(neighbors), CellTypeA.class);
        for(CellTypeA a: onlyAs) {
            State = (a.getData() > 10);
        }   
    }   
}   

顺便问一下,你在循环中给State赋值时是不是想用|=


谢谢!无论我是否使用Guava,这都让我清楚地了解了如何根据user2864740的评论“隐藏”instanceof的方法。 - Stephen Carlson
1
我本意确实是使用 |=,但这相当随意——它并不能代表实际执行的操作。 - Stephen Carlson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接