Object orientation vs Efficiency

I'm developing a chess program in Java and considering the following problem:

  • The Rook piece requires implementation for moving in straight lines.
  • The Bishop piece requires implementation for moving in diagonal lines.
  • However,

  • The Queen piece requires implementation for both of the above movement patterns.
  • I can't think of a clean solution to modelling this relationship, I have considered some but none of them are both compliant with good object-orientated design and code efficient.

  • Java doesn't support multiple inheritance, so Queen cannot borrow implementation from Rook and Bishop

  • If Rook and Bishop extended Queen, I'd need to extract the logic for each kind of movement into separate methods, this would serious bloat my current design for how movement is validated.

  • Neither of the above solutions seem elegant enough to beat just:

  • Putting ALL of the movement implementation into the parent class of all the pieces, this way they all can share all of the common implementation (of which there is quite a bit)
  • I'm aware solution 3 is in violation of good Java design, but in this case, that design pattern seems to only be forcing bloated, inelegant solutions.

    Probably this could be avoided with a complete restructuring of the program, but everything up to this point looks pretty efficient to me, does good OO design always come at the cost of directness of functionality and structure? Is my approach just wrong for the style of the language?

    How would you solve this problem?


    While some classes might behave in a similar way, this does not automatically mean that they are in one hierarchy!

    For example, both a Human and a Crab can move sideways, but it is silly for a Human to extend Crab .

    If you really want to re-use movement code, you can use encapsulation, use a Movement type and make it like this:

    class Human
    {
       List<Movement> movements;
    }
    
    class Crab
    {
        List<Movement> movements;
    }
    
    class MoveSideWays extends Movement
    {
          move();
    }
    
    class MoveForward extends Movement
    {
          move();
    }
    

    But it feels like over-engineering. I would have a Piece class with getPossibleMoves() and just implement it directly. There is not too much overlap and Rooks have specialized movements (Castling) as well.

    class Rook extends Piece
    {
       List<Move> getPossibleMoves()  {...}
    }
    
    class Queen extends Piece
    {
       List<Move> getPossibleMoves() {...}
    }
    

    You should not add a superclass-subclass relations to the individual pieces. The Queen is not the special case of the Rook, neither the Rook is the special case of the Queen. They are just different pieces. You may create an interface (or an abstract class) Piece and provide different implementations like Rook , Bishop , Queen and so on.


    You could move both methods to the superclass, but make them protected static (you could also put those methods in a PieceHelper ). In the subclasses you can then implement the adequate methods, referencing to one or the other of those methods (making them public ).

    Superclass:

    abstract class Piece {
        protected static void moveStraight(Piece p) {...}
        protected static void moveDiagonal(Piece p) {...}
    }
    

    (Optional) Interfaces:

    interface DiagonalMover {
         void moveDiagonal();
    }
    interface StraightMover {
         void moveStraight();
    }
    

    Subclasses:

    class Rook extends Piece implements StraightMover {
        public void moveStraight() {Piece.moveStraight(this);}
    }
    class Bishop extends Piece implements DiagonalMover {
        public void moveDiagonal() {Piece.moveDiagonal(this);}
    }
    class Queen extends Piece implements StraightMover, DiagonalMover {
        public void moveStraight() {Piece.moveStraight(this);}
        public void moveDiagonal() {Piece.moveDiagonal(this);}
    }
    
    链接地址: http://www.djcxy.com/p/84624.html

    上一篇: 移动一块

    下一篇: 面向对象与效率