티스토리 뷰

반응형

태그 달린 클래스

두 가지 이상의 의미를 표현할 수 있고 현재 표현하는 의미를 태그 값으로 알려주는 클래스

public class Figure {
    enum Shape {RECTANGLE, CIRCLE}

    // 태그
    private final Shape shape;

    // 이 필드들은 사각형일때만 사용
    private final double length;
    private final double width;

    // 이 필드는 원형일때만 사용
    private final double radius;

    //원용 생성자
    public Figure(Shape shape, double radius) {
        this.shape = shape;
        this.length = 0;
        this.width = 0;
        this.radius = radius;
    }

    //사각형 생성자
    public Figure(Shape shape, double length, double width) {
        this.shape = shape;
        this.length = length;
        this.width = width;
        this.radius = 0;
    }

    public double area() {
        switch (shape) {
            case RECTANGLE:
                return length * width;
            case CIRCLE:
                return Math.PI * (radius * radius);
            default:
                throw new IllegalArgumentException();
        }
    }
}

 

 

태그달린 클래스의 단점

  • 열거 타입 선언, 태그 필드, switch문 등 쓸데 없는 코드가 많고 여러 구현이 다 있어서 가독성 안좋음
  • 필드들을 final로 선언하려면 현재 쓰이지 않는 필드들까지 생성자에서 초기화해야함
  • 또 다른 의미를 추가하기 위해서 코드를 수정해야함
  • 인스턴스 타입만으로 현재 나타내는 의미를 알 수 없음

 

 

클래스 계층 구조를 활용하는 서브타이핑

태그 달린 클래스를 클래스 계층 구조로 바꾸자.

1) 계층 구조의 루트가 될 추상 클래스를 정의

2) 태그 값에 따라 달라지는 동작 메서드들을 루트 클래스의 추상 메서드로 선언

3) 태그 값에 상관없이 일정한 동작을 하는 메서드들을 루트 클래스에 일반 메서드로 선언

4) 모든 하위 클래스에서 공통으로 사용되는 데이터 필드들도 모두 루트 클래스에 선언

5) 루트 클래스를 확장한 구체 클래스를 의미별로 하나씩 정의

6) 각 하위 클래스에는 각자의 의미에 해당하는 데이터 필드를 추가

 

다음은 태그 달린 클래스의 예제를 클래스 계층 구조로 변환한 코드이다.

public abstract class Figure {
    public abstract double area();
}

public class Circle extends Figure {
    private final double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double area() {
        return Math.PI * (radius * radius);
    }
}

public class Rectangle extends Figure{
    private final double length;
    private final double width;

    public Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }

    @Override
    public double area() {
        return length * width;
    }
}
  • 각 클래스의 생성자가 모든 필드를 남김 없이 초기화하고 추상 메서드를 구현했는지 컴파일러가 확인해준다.
  • 루트 클래스와 독립적으로 계층 구조를 확장하고 사용할 수 있다.
  • 타입이 의미별로 따로 존재

 

결론

태그 달린 클래스를 쓰지 말고 계층 구조로 대체해라.

반응형
댓글
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday