简体   繁体   English

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

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

Say I have the following class, with a list as a field: 说我有以下课程,其中有一个列表作为字段:

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;
    }
}

What would be the best way to ensure the list is in a valid state each time elements are added/removed ? 每次添加/删除元素时,确保列表处于有效状态最佳方法是什么? (Currently the Tile class doesn't contain any setters so I don't need to worry about elements being modified.) (当前Tile类不包含任何设置器,因此我不必担心元素被修改。)

One possible way is to add a boolean field valid , and a method that updates valid , called after each time an element is added/removed: 一种可能的方法是添加一个布尔字段valid ,并在每次添加/删除元素后调用一个更新valid的方法

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

Example usage: 用法示例:

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

However, with this there is the possibility of the valid field becoming inconsistent with the list (eg if one forgets to call updateValid after adding/removing an element). 但是,这样做有可能使valid字段与列表不一致(例如,如果在添加/删除元素后忘记调用updateValid )。

Edit 编辑

I've since realised a simpler way is to just have a method returning a boolean rather than updating a boolean field, but I'm not sure if this is ideal as it's still possible for the list to be in an invalid state. 从那以后,我意识到一种更简单的方法是让方法返回一个布尔值而不是更新一个布尔值字段,但是我不确定这是否理想,因为列表仍然有可能处于无效状态。

The safest solution is to expose individual methods controlling access to the list, instead exposing the entire object: 最安全的解决方案是公开控制列表访问权的各个方法,而不是公开整个对象:

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);
    }
}

If your validation logic involves other elements in the list, you can calculate it after inserting: 如果您的验证逻辑涉及列表中的其他元素,则可以在插入后进行计算:

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

Another approach would be to use lazy validation instead of expecting the client to call an extra method: 另一种方法是使用惰性验证,而不是期望客户端调用额外的方法:

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

Depending on your read/write ratio, this could be more or less expensive than the eager validation you're proposing. 根据您的读/写比率,这可能比您提议的急切验证昂贵或更低。

The updateValid() method is a good idea to validate the adding/removing operation. updateValid()方法是验证添加/删除操作的一个好主意。
To force the constraint, this method should not be called by client of the class as in your usage example but by the internal of the class, that is : any method of Group that modifies the List should call the private updateValid() method. 为了强加约束,该方法不应由您的用法示例中的类的客户端调用,而应由类的内部调用,即:修改List的Group的任何方法都应调用私有updateValid()方法。

Besides, which is the usefulness of the boolean valid field? 此外, boolean valid字段的用处是什么? If a validation fails, should you not stop the processing and throw an exception ? 如果验证失败,您是否应该停止处理并引发异常?
Otherwise, it means that the current state of the Group object could be inconsistent. 否则,这意味着Group对象的当前状态可能会不一致。 Which seems undesirable. 这似乎是不可取的。
You could do it for example : 您可以例如这样做:

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

At last, as shmosel said, you should also avoid to provide a public method that get the real list. 最后,正如shmosel所说,您还应该避免提供提供获取真实列表的公共方法。 You could do a defensive copy to avoid change by the clients : 您可以进行防御性复制以避免客户更改:

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

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

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