该问题仅用于询问如何处理对象的方法,该方法检查与调用方法相同的条件并引发相同的异常类型。由于问题的性质,它变成了有关类设计的问题。

我正在为国际象棋程序设计类设计。我最初使用允许您Chessboard个片段的方法制作了一个put类。原因是:


这是一成不变的,我发现反复创建新的木板对象只是为了初始化它似乎是不必要的。
理想情况下,该板应该一块装满,然后通过Chessboard的界面对板进行进一步的更改。


我做了一个可变的PieceSet类,该类在Chessboard构造函数中传递。

// Showing as interface instead of class, because implementation is not important
public interface PieceSet
{
    void putBishop(Square square, Color color) throws UndefinedSquareException;

    void putKing(Square square, Color color) throws UndefinedSquareException;

    void putKnight(Square square, Color color) throws UndefinedSquareException;

    void putPawn(Square square, Color color) throws UndefinedSquareException;

    void putQueen(Square square, Color color) throws UndefinedSquareException;

    void putRook(Square square, Color color) throws UndefinedSquareException;

    void removePiece(Square square);

    void relocate(Square fromSquare, Square toSquare) throws UndefinedSquareException;
}


PieceSet的实现中,这些方法将使用防护来检查空平方

if(null == square)
    throw new UndefinedSquareException(...);


例如,Chessboard类将使用PieceSet类,如下所示:

public final class Chessboard
{
    private PieceSet pieces;

    public Chessboard()
    {
        this.pieces = new PieceSet();
    }

    public Chessboard(PieceSet initialPieces)
    {
        this.pieces = new PieceSet(initialPieces);
    }

    public Chessboard removePiece(Square square) throws UndefinedSquareException
    {
        /*
         * Check for null here and throw exception??
         * PieceSet does the same thing.
         */

        PieceSet newPieces = new PieceSet(this.pieces);

        newPieces.removePiece(square);

        return new Chessboard(newPieces);
    }

    public Chessboard movePiece(Square fromSquare, Square toSquare)  throws UndefinedSquareException
    {
        /*
         * Check for null here and throw exception??
         * PieceSet does the same thing.
         */
        PieceSet newPieces = new PieceSet(this.pieces);

        newPieces.relocate(fromSquare, toSquare);

        return new Chessboard(newPieces);
    }
}


然后的问题是,由于Chessboard也接收Square类型的参数,并且它们不应该是null,我是否还要在ChessboardremovePiecemovePiece方法中设置防护措施?

if(null == square)
    throw new UndefinedSquareException(...);


另一个想法

我的另一个想法是将PieceSet建模为Chessboard的构建器(尽管PieceSet可能不再是一个好名字,但我不会更改示例的名称)。我以为,由于PieceSet的最初想法是使用它来创建填充的Chessboard,所以我将使PieceSet负责而不是将其传递给Chessboard

public interface PieceSet
{
    putBishop(Square square, Color color) throws UndefinedSquareException;

    putKing(Square square, Color color) throws UndefinedSquareException;

    // Same from above, etc. EXCEPT no remove or relocate methods

    // This is new
    Chessboard createBoard();

}

// The Chessboard doesn't have to use PieceSet. It can be implemented using any data structure to store pieces.
public final class Chessboard
{
    private Map<Square, Piece>pieces;

    public Chessboard(Map<Square, Piece> initialPieces)
    {
        this.pieces = new HashMap<Square, Piece>(initialPieces);
    }

    public Chessboard removePiece(Square square)
    {
        // No more duplication of checking for null square, and throwing exception
    }

    public Chessboard movePiece(Square fromSquare, Square toSquare)
    {
        // No more duplication of checking for null square, and throwing exception
    }
}

最佳答案

总的来说,我们强烈认为接口应该抛出一个检查异常。此外,我们要装饰提供该接口实现的策略对象。最后,我们认为接口中的已检查异常适用于装饰器的调用者。在这种情况下,如果需要将委托抛出的异常传递给装饰器的调用者,那么可以,您将在装饰器中抛出相同的异常。

但具体针对Chessboard问题:我不确定我是否同意UndefinedSquareException甚至应该是经过检查的异常。为什么使用此API的用户曾经提供对空Square的引用,或未由此Chessboard管理的Square的引用,并希望恢复?结果,我倾向于认为UndefinedSquareException扩展了RuntimeException,根本不需要在您的签名中,或者Chessboard捕获了来自PieceSet的已检查异常并在其位置抛出RuntimeException。

希望这对您有所帮助-乐于阅读您的问题并思考问题。

关于java - 当委托(delegate)方法具有相同的防护时,如何处理防护子句并引发异常?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20448044/

10-11 06:45