You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
인터페이스라고해서 클래스를 선언하는 부분에서 implements 키워드를 써서 어떤 자바 인터페이스를 구현하는 클래스를 만든는게 아니다.
일반적으로 어떤 상위 형식(클래스, 인터페이스 등)에 있는 메소드를 구현하는 구상 클래스는 그 상위 형식의 인터페이스를 구현하는 클래스라고 생각하면 된다.
디자인 원칙
애플리케이션에서 달라지는 부분을 찾아 내고, 달라지지 않는 부분으로부터 분리 시킨다.
달라지는 부분을 찾아서 나머지 코드에 영향을 주지 않도록 "캡슐화" 한다.
그러면 코드를 변경하는 과정에서 의도하지 않은 일이 일어나는 것을 줄이면서 시스템의 유연성은 향상시킬 수 있다.
구현이 아닌 인터페이스에 맞춰서 프로그래밍 한다.
실제 실행시에 쓰이는 객체가 코드에 의해서 고정되지 않도록, 어떤 상위(supertype)에 맞춰서 프로그래밍함으로써 다형성을 활용해야한다.
서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.
느슨하게 결합하는 디자인을 사용하면 변경 사항이 생겨도 무난히 처리할 수 있는 유연한 객체지향 시스템을 구축할 수 있다.
객체 사이의 상호의존성을 최소화할 수 있기 때문이다.
OCP(Open-Closed Principle)
클래스는 확장에 대해서는 열려있어야 하지만 코드 변경에 대해서는 닫혀있어야 한다.
이 규칙을 잘 지키면 급변하는 주변 환경에 잘 적응할 수 있으면서도 강하고 튼튼한 디자인을 만들 수 있다.
DIP(Dependency Inversion Principle) 의존성 뒤집기 원칙
추상화된 것에 의존하도록 만들어야한다.
구상 클래스에 의존하도록 만들지 않도록 한다.
이 원칙은 고수준 구성요소가 저수준 구성요소에 의존하면 안 된다는 것이 내포되어있다.
추상화된 것에 의존하라
추상화된 것에 의존하라, 구상 클래스에 의존하지 않도록 한다.
DIP 가이드 라인
어떤 변수에도 구상 클래스에 대한 레퍼런스를 저장하지 말아야 한다.
new 연산자를 사용하면 구상 클래스에 대한 레퍼런스를 사용하게되는 것이다.
팩토리를 써서 구상 클래스에 대한 레퍼런스를 변수에 저장하는 일을 미리 방지한다.
구상 클래스에서 유도된 클래스를 만들지 말아야 한다.
구상 클래스에서 유도된 클래스를 만들면 특정 구상 클래스에 의존하게 된다.
인터페이스나 추상 클래스처럼 추상화된 것으로부터 클래스를 만들어야 한다.
베이스 클래스에 이미 구현되어있던 메소드를 오버라이드하지 말아야 한다.
이미 구현되어있는 메소드를 오버라이드 한다는 것은 애초부터 베이스 클래스가 제대로 추상화 될 것이 아니었다고 볼 수 있다.
베이스 클래스에서 메소드를 정의할 때는 모든 서브 클래스에서 공유할 수 있는 것만 정의해야 한다.
데메테르의 법칙(디미터 법칙) & 최소 지식 원칙
정말 친한 치구하고 얘기하고, 낯선이에게 메세지를 말하지 마라
데메테르의 법칙은 간단하게 의존성을 줄이는 것이다.
// 원칙을 따르지 않는 경우classTest {
publicfloatgetTemp() {
Thermometerthermometer = sation.getThermometer();
returnthermometer.getTemperature();
}
}
// 원칙을 따른 경우classTest2 {
publicfloatgetTemp() {
returnstation.getTemperature();
}
}
첫번 쨰는 의존하는 클래스 객체를 두개를 의존한다. 만약에 thermometer가 바뀌게 되는 경우 Test Class 또한 변하겐된다.
두번 째는 의존하는 클래스 객체가 한개이며 원칙을 잘 지킨 케이스이다.
메서드 호출 가이드 라인
객체 자체의 메서드들
메서드에 매개변수로 전달된 객체
그 메서드에 생성하거나 인스턴스를 만든 객체
그 객체에 구성하는 구성요소
publicclassCar {
// 구성 요소의 메서드는 호출 가능Engineengine;
publicCar() {
// 엔진 초기화 등을 처리
}
publicvoidstart(keyKey) {
// 새로운 객체를 생성 이 객체의 메서드를 호출 가능Doorsdoors = newDoors();
// 매개변수로 전달된 객체의 메서드 호출 가능booleanauthorized = key.turnes();
if(authorized) {
// 객체의 구성요소의 메서드는 호출 가능engine.start();
// 객체 내에 있는 메서드는 호출 가능updateDashboardDisplay();
// 인스턴스를 만든 객체의 메서드는 호출 가능doors.lock();
}
}
publicvoidupdateDashboardDisplay() {
// 디스플레이 갱신
}
}
Java의 System.out.println 데메테르의 법칙에 어긋난다.
헐리우드 원칙
"먼저 연락하지 마세요. 저희가 연락 드리겠습니다."
고수준 구성요소가 저수준 구성요소에 의존하고 그 저수준 구성요소가 다시 고수준 구성요소에 의존하면서 "의존성 부패(dependency rot)"가 발생한다.
헐리우드 원칙을 활용하면 해당 의존성 부패를 방지가 가능하다.
즉 고수준 구성요소에서 저수준 구성요소에게 "먼저 연락하지 말아라, 제가 먼저 연락 드리겠다"라고 얘기하는 것과 같다.
사실 저수준 구성요소에서도 상속 계층구조상 위에 있는 클래스에서 정의한 메서드를 상속을 통해서 호출하게되는 경우가 빈번하지만 저수준과 고수준 사이에 확연하게 드러나는 순환 의존성이 생기는 것은 파하는게 좋다.
단일 역할 원칙
"클래스를 바꾸는 이유는 한 가지 뿐이어야 한다."
어떤 클래스에서 맡고 있는 모든 역할들은 나중에 코드 변화를 불러올 수 있다.
역할이 두개 이상 있으면 바뀔 수 있는 부분이 두가지 이상이 되는 것이다.
해당 원칙에 따라 한 클래스에서는 한 가지 역할만 맡도록 해야 한다.
응집도
한 클래스 또는 모듈이 특정 목적 또는 역할을 얼마나 일관되게 지원하는지를 나타내는 척도라고 할 수 있다.
어떤 모듈 또는 클래스의 응집도가 높다는 것은 이련의 서로 연관되어 기능이 묶여있다는 것
응집도가 낮다는 것은 서로 상관 없는 기능들이 묶여있다는 것을 뜻한다.
Detail
즉 코드에 새로운 요구사항이 있을 때 마다 바뀌는 부분이 있다면 그 행동을 바뀌지 않는 다른 부분으로부터 골라내서 분리해야 한다.
정리 => 바뀌는 부분은 따로 뽑아서 캡슐화, 그렇게하면 나중에 바뀌지 않는 부분에는
영향을 미치지 않은 채로 그 부분만 고치거나 확장할 수 있다.
모든 패턴은 시스템의 일부분을 다른 부분과 독립적으로 변환 시킬 수 있는 방법을 제공하기 위한것이다.