네로개발일기

개발자 네로의 개발 일기, 자바를 좋아합니다 !

반응형

# 태그 달린 클래스보다는 클래스 계층 구조를 활용하라.

 

## 태그 달린 클래스
- 두 가지 이상의 기능을 가지고 있으며, 그 중에서 어떠한 능력을 갖고 있는지 나타내는 태그(tag) 필드가 있는 클래스를 태그 달린 클래스라고 말한다. 이 클래스는 아래와 같은 형태를 가지고 있다.
class Figure {
  enum Shape {
    RECTANGLE, CIRCLE
  };

  final Shape shape; // 태그 필드 

  // 사각형(RECTANGLE)일 때
  double length;
  double width;

  // 원(CIRCLE)일 때
  double radius;

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

  // 원용 생성자
  Figure(double radius) {
    shape = Shape.CIRCLE;
    this.radius = radius;
  }

  double area() {
    switch(shape) {
      case RECTANGLE:
        return length * width;
      case CIRCLE:
        return Math.PI * (radius * radius);
      default:
        throw new AssertionError(shape);
    }
  }
}
 
### 태그 달린 클래스의 단점
1. 열거(enum) 타입 선언, 태그 필드, switch 문장 등 쓸데 없는 코드가 많다.
2. 여러 구현이 하나의 클래스에 혼합되어 있어서 가독성이 좋지 않다.
3. 다른 의미를 위한 코드가 함께 있으니 상대적으로 메모리도 더 차지한다.
4. 필드를 final로 선어하려면 해당 의미에 사용되지 않는 필드까지 생성자에서 초기화해야 한다.
5. 또 다른 의미를 추가하려면 코드를 수정해야 한다. 특히 switch 문장에도
6. 인스턴스 타입만으로는 현재 나타내는 의미를 파악하기 어렵다.

 

## 개선 => 클래스 계층구조
태그 달린 클래스 형태를 클래스 계층 구조로 바꿔보자
### 클래스 계층 구조로 만드는 방법
1. 계층 구조의 루트(root)가 될 추상 클래스를 정의한다.
2. 태그 값에 따라 동작이 달라지는 메서드들을 루트 클래스에 추상 메서드로 선언한다.
3. 태그 값에 상관없이 동작이 일정한 메서드들을 루트 클래스에 일반 메서드로 추가한다.
4. 모든 하위 클래스에서 공통으로 사용하는 데이터 필드들도 전부 루트 클래스로 올린다.
5. 루트 클래스를 확장한 구체 클래스를 의미별로 하나씩 정의한다.
6. 각 하위 클래스에는 각자의 의미에 해당하는 데이터 필드를 넣는다.
7. 루트 클래스가 정의한 추상 메서드를 각자의 의미에 맞게 구현한다.
abstract class Figure {
  abstract double area();
}

class Circle extends Figure {
  final dobule radius;
  Circle(double radius) {
    this.radius = radius;
  }
  @Override
  double area() {
    return Math.PI * (radius * radius);
  }
}

class Rectangle extends Figure {
  final double length;
  final double width;
  Rectangle(double length, double width) {
    this.length = length;
    this.width = width;
  }
  @Override
  double area() {
    return length * width;
  }
}

 

- 간결하고 명확해졌으며, 쓸데없는 코드들이 모두 사라졌다. 각 의미를 독립된 클래스에 담았기 때문에 관련없는 데이터 필드는 모두 제거되었다.
- 타입 사이의 자연스러운 계층 관계를 반영할 수 있어서 유연성은 물론 컴파일 타임에서의 타입 검사 능력도 높여준다. 또한 클래스 계층 구조라면, 아래와 같이 정사각형(Square)가 추가될 때도 간단하게 반영할 수 있다.
class Square extends Rectangle {
  Square(double side) {
    super(side, side);
  }
}​



## 정리
- 태그 달린 클래스를 써야 하는 상황은 거의 없다.
- 새로운 클래스를 작성하는 데 태그 필드가 등장한다면 태그를 없애고 계층 구조로 대체하는 방법을 생각해보자.
- 기존 클래스가 태그 필드를 사용하고 있다면 계층 구조로 리팩터링 하는 것을 고민하자.
728x90
반응형
blog image

Written by ner.o

개발자 네로의 개발 일기, 자바를 좋아합니다 !