-
Notifications
You must be signed in to change notification settings - Fork 0
박정제 1주차 체스 학습 일지
CodingLuizy edited this page Jul 1, 2024
·
1 revision
객체지향적으로 설계를 하는건 어떤걸까?
- SOLID, OOP ...
객체마다의 역할과 책임을 잘 분리해두는것 그렇다면, 핵심 관심사가 무엇이고, 그것을 유연하게 잘 적용하려면 어떻게 해야할까?
💡 핵심 관심사 : 규칙적용
- 모든 이동은 규칙에 따라 이동한다 (행마법, 캐슬링…)
- 제일 오랫동안 집중적으로 구현할 부분이 규칙과 이동이라고 생각
- 규칙을
enum
으로 정의하고 규착마다의 이동 방식을 구현하는 방법으로 구현
출처 : Java Enum 활용기
기본적인 장점:
- IDE 지원: 자동완성, 오타 검증, 텍스트 리팩토링 등.
- 허용 값 제한: 허용 가능한 값을 제한.
- 리팩토링 최소화: 변경 범위 최소화.
- 추가 수정 불필요: Enum 코드 외 수정 불필요.
추가적인 Java Enum의 장점:
- Java의 Enum은 완전한 클래스 기능을 가짐.
예제 소개:
-
데이터 연관관계 표현:
- 문제: 서로 다른 데이터 형태("Y"/"N", "1"/"0", true/false) 사용.
- 해결: Enum으로 추출하여 데이터 그룹화.
public enum TableStatus { YES("Y", "1", true), NO("N", "0", false); // ... getter methods }
-
상태와 행위를 한곳에서 관리:
- 문제: 다른 계산식을 적용하는 메소드 관리 어려움.
- 해결: Enum을 통해 각 상태가 자체 계산식을 갖도록 지정.
public enum Calculator { CALC_A { @Override public long calculate(long input) { return input; } }, CALC_B { @Override public long calculate(long input) { return input + 10; } }, CALC_C { @Override public long calculate(long input) { return input * 3; } }; public abstract long calculate(long input); }
-
데이터 그룹 관리:
- 문제: 결제 종류와 결제 수단 관계를 문자열과 메소드로 관리.
- 해결: Enum을 사용하여 관계 명확히 표현.
public enum PayGroup { CARD("신용카드", Arrays.asList("페이코", "카카오페이")), CASH("현금", Arrays.asList("계좌이체", "휴대폰결제")); // ... methods for managing pay codes }
-
관리 주체를 DB에서 객체로 전환:
- 문제: 코드 테이블을 DB에서 관리하면서 발생하는 문제점.
- 해결: 카테고리 데이터를 Enum으로 전환하고, 팩토리와 인터페이스로 일관된 관리.
public enum Category implements BaseEnum { FOOD("음식"), ELECTRONICS("전자제품"); // ... implementation of BaseEnum interface }
결론:
- 장점: 코드 이해도와 유지보수성 향상, 문맥(Context) 표현 가능.
- 추가 고려사항: 자주 변경되는 데이터는 별도로 관리 필요.
마무리:
- Enum을 통해 코드의 가독성과 유지보수성을 높이며, 실용적이고 효율적인 개발이 가능함.
- 기물을 일반화 시킨
Piece.class
구현
classDiagram
direction BT
class Bishop {
+ double DEFAULT_POINT
+ char WHITE_REPRESENTATION
+ char BLACK_REPRESENTATION
}
class King {
+ char BLACK_REPRESENTATION
+ double DEFAULT_POINT
+ char WHITE_REPRESENTATION
}
class Knight {
+ char WHITE_REPRESENTATION
+ char BLACK_REPRESENTATION
+ double DEFAULT_POINT
}
class Pawn {
+ char WHITE_REPRESENTATION
+ char BLACK_REPRESENTATION
+ double DEFAULT_POINT
}
class Piece {
# List~Direction~ movableDirections
# List~MoveRule~ specialMoveRules
# Color color
# char representation
+ int MAX_MOVE_DISTANCE
- boolean isMoved
# int moveDistance
}
class Queen {
+ char BLACK_REPRESENTATION
+ double DEFAULT_POINT
+ char WHITE_REPRESENTATION
}
class Rook {
+ char WHITE_REPRESENTATION
+ char BLACK_REPRESENTATION
+ double DEFAULT_POINT
}
Bishop --> Piece
King --> Piece
Knight --> Piece
Pawn --> Piece
Queen --> Piece
Rook --> Piece
- 각 기물들은 각각의 특성들을 가지고 있다
- 이동 방향과 이동 거리 : 행마법에 따른 움직임
- 특수한 이동 규칙 : 폰의 이동, 캐슬링 등
- 모든 기물의 이동은 규칙에 따라 이동한다
-
MoveRule
enum class로 이동규칙을 정의하고 각 enum class에 이동방식과 이동을 구현했다. - chess/move/MoveRule.java
public enum MoveRule{
Common {
public void move(Board board, String source, String target) {}
public Map<ChessPoint, MoveRule> getMovablePoints(Board board, ChessPoint source, Piece piece) {}
},
Castling {
public void move(Board board, String source, String target) {}
public Map<ChessPoint, MoveRule> getMovablePoints(Board board, ChessPoint kingPoint, Piece piece) {}
@Override
public boolean isAttackable() {return false;}
},
PawnMove {
public void move(Board board, String source, String target) {}
public Map<ChessPoint, MoveRule> getMovablePoints(Board board, ChessPoint source, Piece piece) {}
},
Promotion {
public void move(Board board, String source, String target) {}
public Map<ChessPoint, MoveRule> getMovablePoints(Board board, ChessPoint source, Piece piece) {}
},
None {
public void move(Board board, String source, String target) {}
public Map<ChessPoint, MoveRule> getMovablePoints(Board board, ChessPoint source, Piece piece) {}
};
public void adapt(Map<ChessPoint, MoveRule> map, Board board, ChessPoint source, Piece piece, boolean onlyAttackable) {
if (onlyAttackable) {
if (this.isAttackable()) {
map.putAll(this.getMovablePoints(board, source, piece));
}
}
else {
map.putAll(this.getMovablePoints(board, source, piece));
}
}
public abstract void move(Board board, String source, String target);
public abstract Map<ChessPoint, MoveRule> getMovablePoints(Board board, ChessPoint source, Piece piece);
public boolean isAttackable() {
return true;
}
}
- 따라서, 각 기물에 적용되는 규칙만 알고 있으면 된다.
- 'Board' 클래스의
move
메소드를 통해 기물을 이동시킨다. - 출발 위치의 기물이 목적위치까지 이동할 수 있는 규칙을 찾아 이동시킨다.
- chess/Board.java
public void move(String source, String target) {
Piece piece = findPiece(source);
MoveRule moveRule = piece.getMoveRule(this, ChessPoint.of(source), ChessPoint.of(target));
moveRule.move(this, source, target);
}
- 이동 가능한 위치인지 파악하기 위해서는
MoveRule
을 적용한다 - chess/piece/Piece.java