IS-A 관계와 HAS-A 관계
- IS-A 관계
- 일반적인 클래스와 구체적인 클래스의 관계
- 클래스간의 상속은 종속성이 강하므로 꼭 필요한 경우 사용하는 것이 좋다.
- 상속은 코드 재사용을 위한 방법이 아니다.
- HAS-A 관계
- 이미 잘 만들어진 라이브러리나 클래스를 재사용하는 방법
- 사용할 클래스를 포함하여 그 기능을 해당 클래스로 위임한다.
- 클래스간의 종속성이 약하다.
- 이미 잘 만들어진 클래스를 재사용하기 위해서는 상속이 아닌 위임을 사용한다.
- IS-A 관계가 아닌 클래스간의 상속은 HAS-A로 리팩토링 한다.
상속
상속은 좀 더 일반적인 클래스에서 그보다 구체적인 클래스가 여러개 생길 수 있는 경우에 사용한다.
상속을 통한 방법은 결합도가 강하기 때문에, 코드의 재사용의 목적으로는 사용하지 않는 것이 좋다.
리팩토링 전 - 학생 클래스가 과목 클래스를 상속한 경우
- 처음엔 전공과목 하나만 있었지만, 점점 과목이 추가 됨.
- 본문에 예시를 복붙하지는 않는데, 예시에서는 Subject 클래스의 값을 사용하려고 extends 받아서 구현하도록 되어 있었음. 이 관계에서 Student와 Subject 간의 관계는 IS-A 관계가 아니라 상속받아서 사용하는 것은 부적절하다.
- 따라서 이런 경우 Has-A 관계로 구성하여 구현하는 것이 옳다.
리팩토링 후 - Student 학생 클래스에서 Subject 클래스를 상속 받는 것이 아닌, 구성하여 사용하도록 리팩토링 함
package refactoringisawithhasa;
import java.util.ArrayList;
public class Student{
private String studentName;
private String studentId;
private Subject majorSubject;
private ArrayList<Subject> subjectList = new ArrayList<Subject>();
public Student(String studentName, String studentId, String majorSubjectName, int majorCode) {
this.studentName = studentName;
this.studentId = studentId;
this.majorSubject = new Subject(majorSubjectName, majorCode);
subjectList.add(this.majorSubject);
}
public void addSubject(String subjectName, int subjectCode) {
Subject subject = new Subject(subjectName, subjectCode);
subjectList.add(subject);
}
public void setSubjectScore(int subjectCode, int score) {
for(Subject subject : subjectList) {
int code = subject.getSubjectCode();
if(subjectCode == code) {
subject.setScore(score);
return;
}
}
System.out.println("no subject");
}
public void getReport() {
int total = 0;
System.out.println(studentName + "님의 전공과목은 " + majorSubject.getSubjectName() + "이고, 점수는 : " + majorSubject.getScore() + "입니다.");
for(Subject subject : subjectList) {
System.out.println(subject.getSubjectName() + " : " + subject.getScore());
total += subject.getScore();
}
System.out.println("total : " + total);
}
}
package refactoringisawithhasa;
public class Subject {
private String subjectName;
private int subjectCode;
private int score;
public Subject(String subjectName, int subjectCode) {
super();
this.subjectName = subjectName;
this.subjectCode = subjectCode;
}
public String getSubjectName() {
return subjectName;
}
public void setSubjectName(String subjectName) {
this.subjectName = subjectName;
}
public int getSubjectCode() {
return subjectCode;
}
public void setSubjectCode(int subjectCode) {
this.subjectCode = subjectCode;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
package refactoringisawithhasa;
public class Main {
public static void main(String[] args) {
Student studentLee = new Student("Lee", "12345", "국어국문", 100);
Student studentKim = new Student("Kim", "67890", "영어영문", 200);
studentLee.addSubject("수학", 300);
studentLee.setSubjectScore(100, 90);
studentLee.setSubjectScore(300, 100);
studentKim.addSubject("수학", 300);
studentKim.setSubjectScore(200, 100);
studentKim.setSubjectScore(300, 70);
studentLee.getReport();
studentKim.getReport();
}
}
'java > java 리팩토링' 카테고리의 다른 글
07. 전략, 상태패턴 적용하기 (0) | 2023.02.11 |
---|---|
06. 생성자를 팩토리 메서드로 바꾸기 (0) | 2023.02.10 |
05. if-else, if-switch 문의 분류 코드를 하위 클래스로 만들기 (0) | 2023.02.08 |
04. 분류 코드를 클래스로 만들기 (0) | 2023.02.08 |
03. null 객체 사용 (0) | 2023.02.07 |
댓글