繁体   English   中英

每次添加/删除元素时如何验证列表?

[英]How to validate a list each time elements are added/removed?

说我有以下课程,其中有一个列表作为字段:

class Group {
    private List<Tile> tiles;

    public Group(List<Tile> tiles) {
        this.tiles = tiles;
    }

    public Group() {
        this(new LinkedList<>());
    }

    public List<Tile> getTiles() {
        return tiles;
    }
}

每次添加/删除元素时,确保列表处于有效状态最佳方法是什么? (当前Tile类不包含任何设置器,因此我不必担心元素被修改。)

一种可能的方法是添加一个布尔字段valid ,并在每次添加/删除元素后调用一个更新valid的方法

class Group {
    // ...
    private boolean valid;
    // ...
    public void updateValid() {
        // Check list is valid...
        valid = true; // Updates `valid`
    }
}

用法示例:

group.getTiles().add(new Tile());
group.updateValid();

但是,这样做有可能使valid字段与列表不一致(例如,如果在添加/删除元素后忘记调用updateValid )。

编辑

从那以后,我意识到一种更简单的方法是让方法返回一个布尔值而不是更新一个布尔值字段,但是我不确定这是否理想,因为列表仍然有可能处于无效状态。

最安全的解决方案是公开控制列表访问权的各个方法,而不是公开整个对象:

class Group {
    private List<Tile> tiles;

    public Group(List<Tile> tiles) {
        // defensive copy
        this.tiles = new LinkedList<>(tiles);
    }

    public Group() {
        this.tiles = new LinkedList<>();
    }

    public boolean add(Tile tile) {
        // validate *before* inserting
        return validate(tile) && tiles.add(tile);
    }
}

如果您的验证逻辑涉及列表中的其他元素,则可以在插入后进行计算:

public void add(Tile tile) {
    tiles.add(tile);
    updateValid();  // or throw IllegalStateException
}

另一种方法是使用惰性验证,而不是期望客户端调用额外的方法:

public boolean isValid() {
    boolean valid = ... // validation logic here
    return valid;
}

根据您的读/写比率,这可能比您提议的急切验证昂贵或更低。

updateValid()方法是验证添加/删除操作的一个好主意。
为了强加约束,该方法不应由您的用法示例中的类的客户端调用,而应由类的内部调用,即:修改List的Group的任何方法都应调用私有updateValid()方法。

此外, boolean valid字段的用处是什么? 如果验证失败,您是否应该停止处理并引发异常?
否则,这意味着Group对象的当前状态可能会不一致。 这似乎是不可取的。
您可以例如这样做:

private void updateValid() {
     if (...){  // is not valid
         throw new IllegalArgumentException("modification not valid");
     }
}

最后,正如shmosel所说,您还应该避免提供提供获取真实列表的公共方法。 您可以进行防御性复制以避免客户更改:

public List<Tile> getTiles() {
    return new LinkedList(tiles);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM