클래스 간에 기능을 안전하게 이동하고 새 클래스를 만들고 구현 세부 정보를 외부 접근으로부터 숨길 수 있는 방법
메소드가 자체 클래스보다 다른 클래스에서 더 많이 사용된다면 가장 많이 사용되는 클래스로 메소드 이동
클래스를 내부적으로 일관성 있게 만듬
클래스 간의 종속성 감소
필드가 자신의 클래스보다 다른 클래스에서 더 많이 사용될 경우 더 많이 사용되는 클래스로 필드 이동
한 클래스가 여러 작업을 한다면 새 클래스를 만들고 관련 기능을 담당하는 필드와 메소드를 해당 클래스에 배치
단일 책임 원칙을 준수
클래스의 코드가 더 명확하고 이해하기 쉬움
안정적이고 다른 클래스의 변경 사항에 영항을 많이 받지 않음
단일 책임 원칙(Single Responsibility Principle)
모든 클래스는 하나의 책임만 가져야 한다.
클래스가 거의 아무런 기능을 하지 않을 정도로 역할이 작다면 다른 클래스로 모든 기능을 이동
클라이언트가 객체의 위임 클래스를 직접 호출하고 있는 경우 서버에 메서드를 만들어서 대리 객체를 숨김
<변경 전>
class Person {
Department _department;
public Department getDepartment() {
return _department;
}
public void setDepartment(Department arg) {
_department = arg;
}
}
class Department {
private String _chargeCode;
private Person _manager;
public Department (Person manager) {
_manager = manager;
}
public Person getManager() {
return _manager;
}
}
클라이언트가 어떤 사람의 매니저를 알려고 한다면 먼저 그 사람이 속해 있는 부서를 알아야 한다.
manager = john.getDepartment().getManager();
Department 클래스가 매니저 정보를 알려주는 메소드가 있다는 것을 클라이언트가 알게 된다.
Person 클래스에 위임 메소드를 만들어서 Department의 존재를 클라이언트에게 숨기면 결합을 줄일 수 있다.
또한 getDepartment() 접근자를 제거할 수 있다.
(Person 클래스가 부서 등록과 매니저 조회만 한다는 조건 하에)
<변경 후>
class Person {
Department _department;
public void setDepartment(Department arg) {
_department = arg;
}
public Person getManager() {
return _department.getManager();
}
}
class Department {
private String _chargeCode;
private Person _manager;
public Department (Person manager) {
_manager = manager;
}
public Person getManager() {
return _manager;
}
}
모든 클라이언트가 이 Person 클래스의 새로운 메소드를 사용하게 한다.
manager = john.getManager();
서버 클래스에 필요한 메소드가 포함되어 있지 않고 클래스에 메소드를 추가할 수 없다면 클라이언트 클래스에 메소드를 추가하고 서버 클래스의 인스턴스를 인수로 전달
<변경 전>
class Report {
// ...
void sendReport() {
Date nextDay = new Date(previousEnd.getYear(),
previousEnd.getMonth(), previousEnd.getDate() + 1);
// ...
}
}
<변경 후>
class Report {
// ...
void sendReport() {
Date newStart = nextDay(previousEnd);
// ...
}
private static Date nextDay(Date arg) {
return new Date(arg.getYear(), arg.getMonth(), arg.getDate() + 1);
}
}
서버 클래스에 필요한 메소드가 포함되어 있지 않고 클래스에 메소드를 추가할 수 없다면 메소드를 포함하는 새 클래스를 만들고 원래 클래스의 자식 클래스 또는 래퍼(wrapper) 클래스로 만듬
<자식 클래스>
class MfDateSub extends Date {
// 생성자 정의
public MfDateSub (String dateString) {
super(dateString);
}
// 변환 생성자 정의
public MfDateSub (Date arg) {
super(arg.getTime())
}
//필요한 외래 메소드 정의
Date nextDay() {
return new Date (getYear(), getMonth(), getDate() + 1);
}
}
<래퍼 클래스>
class MfDateWrap {
private Date _original;
//생성자 정의
public MfDateWrap(String dateString) {
_original = new Date(dateString);
}
//변환 생성자 정의
public MfDateWrap(Date arg) {
_original = arg;
}
//기존 기능 위임 메소드
public int getYear() {
return _original.getYear();
}
//기존 기능 위임 메소드
public boolean equals (MfDateWrap arg) {
return (toDate().equals(arg.toDate()));
}
//필요한 외래 메소드 정의
Date nextDay() {
return new Date (getYear(), getMonth(), getDate() + 1);
}
}
추가 메소드를 별도의 확장 클래스(자식 or 래퍼)로 이동하면 적합하지 않은 코드로 클라이언트 클래스와 묶여지는 것을 예방
프로그램 구성 요소는 더 일관성 있고 재사용 가능
❓ Foreign Method & Local Extension
소스 코드를 수정할 수 없는 경우에
한두 개의 메소드 → Foreign Method
자식 클래스나 래퍼 클래스 → Local Extension
📑 참고 자료