상세 컨텐츠

본문 제목

분류 코드를 하위 클래스로 치환 (Replace Type Code With Subclass)

자바강좌/리팩토링

by somiyuralove 2020. 2. 3. 22:55

본문

* 분류 코드를 하위 클래스로 치환 (Replace Type Code With Subclass)
- 분류코드마다 하위 클래스를 준비해서 하위 클래스 내부에 동작을 서술하면 코드를 깔끔하게 정리할 수 있습니다.
이게 바로 여기서 배우는 분류 코드를 하위 클래스로 치환 리팩토링임.

- 분류코드 마다 다른 동작을 한다면 switch문을 사용하고 싶어짐. 하지만 객체지향 프로그래밍이라면 switch문은 악취가 남.

- 분류 코드를 하위 클래스로 치환 리팩토링은 하위 클래스라는 '구조'를 새로 만들거나, switch문 하나에 모여 있던 '동작'을
하위 클래스로 배분하게 됨.

* 리팩토링 전 코드

package ReplaceTypeCodeWithSubclasses;

public class Shape {
public static final int TYPECODE_LINE = 0;
public static final int TYPECODE_RECTANGLE = 1;
public static final int TYPECODE_OVAL = 2;

private final int _typecode;
private final int _startx;
private final int _starty;
private final int _endx;
private final int _endy;

protected Shape(int typecode, int startx, int starty, int endx, int endy) {
_typecode = typecode;
_startx = startx;
_endx = endx;
_starty = starty;
_endy = endy;
}

public int getTypeCode() {
return _typecode;
}

public String getName() {
switch(_typecode) {
case TYPECODE_LINE:
return "LINE";
case TYPECODE_RECTANGLE:
return "RECTANGLE";
case TYPECODE_OVAL:
return "OVAL";
default:
return null;
}
}

public String toString() {
return "[ "
+ getName() + ", "
+ "(" + _startx + ", " + _starty + ")-"
+ "(" + _endx + ", " + _endy + ") ]";
}

public void draw() {
switch(_typecode) {
case TYPECODE_LINE:
drawLine();
break;
case TYPECODE_RECTANGLE:
drawRectangle();
break;
case TYPECODE_OVAL:
drawOval();
break;
default:
;
}
}

private void drawLine() {
System.out.println("drawLine: " + this.toString());
}

private void drawRectangle() {
System.out.println("drawRectangle: " + this.toString());
}

private void drawOval() {
System.out.println("drawOval: " + this.toString());
}
}



package ReplaceTypeCodeWithSubclasses;

public class Main {
public static void main(String[] args) {
Shape line = new Shape(Shape.TYPECODE_LINE, 0, 0, 100, 200);
Shape rectangle = new Shape(Shape.TYPECODE_RECTANGLE, 10, 20, 30, 40);
Shape oval = new Shape(Shape.TYPECODE_OVAL, 100, 200, 300, 400);

Shape[] shape = {
line, rectangle, oval
};

for (Shape s : shape) {
s.draw();
}
}
}

* 리팩토링 후 코드

package ReplaceTypeCodeWithSubclasses;

public class Main {
public static void main(String[] args) {
Shape line = Shape.createShape(Shape.TYPECODE_LINE, 0, 0, 100, 200);
Shape rectangle = Shape.createShape(Shape.TYPECODE_RECTANGLE, 10, 20, 30, 40);
Shape oval = Shape.createShape(Shape.TYPECODE_OVAL, 100, 200, 300, 400);

Shape[] shape = {
line, rectangle, oval
};

for (Shape s : shape) {
s.draw();
}
}
}

package ReplaceTypeCodeWithSubclasses;

public abstract class Shape {
public static final int TYPECODE_LINE = 0;
public static final int TYPECODE_RECTANGLE = 1;
public static final int TYPECODE_OVAL = 2;

// private final int _typecode;
private final int _startx;
private final int _starty;
private final int _endx;
private final int _endy;

public static Shape createShape(int typecode, int startx, int starty, int endx, int endy) {
switch(typecode) {
case TYPECODE_LINE:
return new ShapeLine(startx, starty, endx, endy);

case TYPECODE_RECTANGLE:
return new ShapeRectangle(startx, starty, endx, endy);
case TYPECODE_OVAL:
return new ShapeOval(startx, starty, endx, endy);
default:
throw new IllegalArgumentException("typecode =" + typecode);
}
}

protected Shape(/*int typecode, */int startx, int starty, int endx, int endy) {
// _typecode = typecode;
_startx = startx;
_endx = endx;
_starty = starty;
_endy = endy;
}

// public int getTypeCode() {
// return _typecode;
// }

public abstract int getTypecode();

public abstract String getName();


// public String getName() {
// switch(_typecode) {
// case TYPECODE_LINE:
// return "LINE";
// case TYPECODE_RECTANGLE:
// return "RECTANGLE";
// case TYPECODE_OVAL:
// return "OVAL";
// default:
// return null;
// }
// }

public String toString() {
return "[ "
+ getName() + ", "
+ "(" + _startx + ", " + _starty + ")-"
+ "(" + _endx + ", " + _endy + ") ]";
}

public abstract void draw();

// public void draw() {
// switch(_typecode) {
// case TYPECODE_LINE:
// drawLine();
// break;
// case TYPECODE_RECTANGLE:
// drawRectangle();
// break;
// case TYPECODE_OVAL:
// drawOval();
// break;
// default:
// ;
// }
// }


// private void drawLine() {
// System.out.println("drawLine: " + this.toString());
// }
//
// private void drawRectangle() {
// System.out.println("drawRectangle: " + this.toString());
// }
//
// private void drawOval() {
// System.out.println("drawOval: " + this.toString());
// }
}
 
package ReplaceTypeCodeWithSubclasses;

public class ShapeLine extends Shape {

protected ShapeLine(int startx, int starty, int endx, int endy) {
super(startx, starty, endx, endy);
// TODO Auto-generated constructor stub
}

@Override
public int getTypecode() {
// TODO Auto-generated method stub
return Shape.TYPECODE_LINE;
}

@Override
public String getName() {
// TODO Auto-generated method stub
return "LINE";
}

@Override
public void draw() {
// TODO Auto-generated method stub
drawLine();
}

private void drawLine() {
System.out.println("drawLine: " + this.toString());
}
}

package ReplaceTypeCodeWithSubclasses;

public class ShapeOval extends Shape {

protected ShapeOval(int startx, int starty, int endx, int endy) {
super(startx, starty, endx, endy);
// TODO Auto-generated constructor stub
}

@Override
public int getTypecode() {
// TODO Auto-generated method stub
return Shape.TYPECODE_OVAL;
}

@Override
public String getName() {
// TODO Auto-generated method stub
return "OVAL";
}

@Override
public void draw() {
// TODO Auto-generated method stub
drawOval();
}

private void drawOval() {
System.out.println("drawOval: " + this.toString());
}

}

package ReplaceTypeCodeWithSubclasses;

public class ShapeRectangle extends Shape {

protected ShapeRectangle(int startx, int starty, int endx, int endy) {
super(startx, starty, endx, endy);
// TODO Auto-generated constructor stub
}

@Override
public int getTypecode() {
// TODO Auto-generated method stub
return Shape.TYPECODE_RECTANGLE;
}

@Override
public String getName() {
// TODO Auto-generated method stub
return "RECTANGLE";
}

@Override
public void draw() {
// TODO Auto-generated method stub
drawRectangle();

}

private void drawRectangle() {
System.out.println("drawRectangle: " + this.toString());
}

}

관련글 더보기

댓글 영역