태그 달린 클래스는 어거지로 하나의 클래스가 구체적인 표현을 두가지 이상 가진 클래스를 뜻합니다.
태그가 클래스의 구체 동작을 결정하고, 태그는 final
필드로 표현됩니다.
사실 우리는 자바를 정석으로 배워왔고, 객체 지향 프로그래밍이 탄탄히 자리잡힌 시점에서는 이런 클래스 구조를 볼 일이 없을 것 같은데요.
이 개념을 머릿속에 담기보다는 문제점이 무엇인지 생각하면서 읽으면 재밌을 것 같습니다!
아래에서 4가지의 문제점을 설명드릴게요!!
public class Figure {
enum Shape {RECTANGLE, CIRCLE};
// 태그 필드 -> 이 필드 값에 따라서 메서드 내부 동작이 결정된다.
final Shape shape;
//사각형일 때 쓰이는 필드들
double length;
double width;
//원일 때 쓰이는 필드들
double radius;
//원 생성자
public FigureWithTag(double radius) {
this.shape = Shape.CIRCLE;
this.radius = radius;
}
//사각형 생성자
public FigureWithTag(double length, double width) {
this.shape = Shape.RECTANGLE;
this.length = length;
this.width = width;
}
double area() {
switch (shape) {
case RECTANGLE:
return length * width;
case CIRCLE:
return Math.PI * (radius * radius);
default:
throw new AssertionError(shape);
}
}
}
단일 책임 원칙(Single Responsibility Principle, SRP)을 지킬 수 있게 되었다.
단일 책임 원칙(SRP) : 한 클래스는 하나의 책임만 가져야 한다
이전에는 한 클래스가 사각형과 원이라는 여러 책임감을 가지고 있었지다.
그러나 클래스 계층 구조로 변경하면, 한 하위 클래스가 그 타입에 대한 하나의 책임을 가져, 응집도가 높아진다.
OCP(Open-Closed Principle) 원칙을 지킬 수 있게 된다.
OCP : 확장에는 열려있고, 수정에는 닫혀있어야 한다
이전에는 사각형 넓이 계산에 수정이 있거나 삼각형이라는 새로운 타입을 추가하고 싶을 떄 관련없는 코드도 수정되어야했다.
새로운 확장에 기존 코드 수정이 필요했다.
그러나 클래스 계층 구조로 변경 후에는, 새로운 타입이 추가되더라도 다른 하위 클래스에 영향을 주지 않는다.
이 밖에 객체 생성 시점이나 별도의 메서드없이는 인스턴스의 구체 타입을 알기 어려웠던 문제점, 낮은 가독성등에 대한 문제점을 해결할 수 있다.
글의 분량이 아쉬운 것 같아서, 위에서 언급한 컴파일 오류에 대해서 추가 포스팅을 해보려고 합니다!
클래스, 메서드, 변수에 final을 사용하면, 컴파일 단계에서 의도하지 않은 변경을 막을 수 있다.
Object보다는 구체적인 타입을 사용해 컴파알 단계에서 오류를 만날 수 있다.
제네릭 타입을 사용하면 타입 안정성을 높일 수 있다.
List numbers = new ArrayList(); //모든 타입이 들어가게 된다.
List<Integer> numbers = new ArrayList<>(); //정수형 타입만 사용하게 강제된다.
이렇게 아이템 23을 정리해봤는데요.
사실 이제는 이런 구조의 클래스를 볼 일이 없지 않나 싶습니다.
더 안전한 코드, 믿을 수 있는 코드를 짜기 위해 노력해보겠습니다.!
해당 글은 카카오테크스터디 중에 작성한 글입니다 🙇♀️
제가 정리하지 않은 나머지 글은 고마운 팀원분들이 정리해주시고 계십니다 🫶더 많은 글을 읽고 싶다면 아래 깃허브를 참고해주세요!