변수와 메서드를 클래스로 묶어 독립적으로 동작하지않도록 하거나 불필요한 정보를 노출시키지않습니다.
캡슐화 예시 - DTO
대표적인 예시중 하나로, 필드를 private 로 접근을 제어하고 그필드에 사용하기위한 getter, setter를 만들어 필드에 접근하는 방식
extends
부모클래스가 가지고있는것을 자식클래스가 확장하는 개념

추상 메서드, 인터페이스, 추상 클래스
구체적인 사실들을 일반화시켜 기술하는 개념으로 필요한 공통점을 추출하고 불필요한 공통점을 제거하는 과정

오버로딩, 오버라이딩,...
같은 이름의 메서드를 여러개의 정의 하되, 매개변수의 타입 또는 개수가 다르도록 정의하는 개념
public class Test {
public static void main(String[] args) {
Test calc = new Test();
System.out.println("add(int a, int b) = " + calc.add(1,2));
System.out.println("add(double a, double b) = " + calc.add(1.5,2.5));
System.out.println("add(int a, int b, int c) = " + calc.add(1,2,3));
}
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
}
자식 클래스가 부모클래스의 메서드를 재정의 하는 행위

부모 클래스의 메서드를 재정의(오버라이딩) 하고 있음을 컴파일러에게 알려주는 역할을 수행하는 어노테이션
사용 이유
하나의 객체는 반드시 하나의 책임(기능, 동작) 을 가져야합니다.
// 단일 책임의 원칙 위반
public Employee(double salary) {
this.salary += salary;
generatePromotionLetter();
}
public void generatePromotionLetter() {
System.out.println("Promotion lefter for" + name) ;
System.out.println("with new salary : " + salary);
}
Employee 클래스는 직원과 관련된 데이터 및 기능을 담당하여야 하며 프로모션 레터를 생성하는 기능도 포함하고 있기 때문에 SRP에 위반함
class PromotionLetterGenerator {
public void generatorPromotionLetter(Employee employee) {
System.out.println("Promotion lefter for" + employee.name) ;
System.out.println("with new salary : " + employee.salary);
}
}
프로모션 레터 생성 기능을 담당하는 별도의 클래스로 분리하여 각각의 클래스는
하나의 책임(기능)을 가지도록 적용
객체의 확장은 개방적으로 열려 있어야 하며, 객체의 수정은 폐쇄적으로 닫혀 있어야 합니다
-> 기능을 추가할 때 기존 코드를 수정하지 않고, 새로운 코드를 추가하여 확장할 수 있는 확장성을 가져야 합니다.
class PromotionLetterGenerator {
public void generatePromotionLetter(Employee employee) {
System.out.println("Promotion lefter for" + employee.name) ;
System.out.println("with new salary : " + employee.salary);
}
}
정규직과 계약직 직원에 대하여 아래와 같이 프로모션 레터를 따로 생성해야할 경우
어떻게 코드를 수정해야할 것인가?
class FullTimeEmployee extends Employee {
public FullTimeEmployee(String name, double salary) {
super(name, salary);
}
@Override
public void generatePromotionLetter() {
System.out.println("Promotion lefter for" + name) ;
System.out.println("with new salary : " + salary);
}
}
기존 Employee 클래스의 generatorPromotionLetter의 기존 코드를 수정하지 않고
상속받음으로써 새로운 코드를 추가하여 확장을 할 수 있도록 적용

객체는 자신이 호출하지 않는 메소드의 의존하지 않아야 한다는 원칙입니다.
-> 인터페이스를 상속 받을 때 사용되지 않는 메소드가 없어야 합니다.
interface EmployeeOperation {
void promote(double increase);
void generatePromotionLetter();
double calculateBounds();
}
EmployeeOperations 인터페이스를 상속 받아야 하고, 아래와 같이 메서드를 사용해야 할 경우 사용되지 않는 메서드가 있으니 ISP에 위반함

1. Employee 클래스 : promote()
2. FullTimeEmployee 클래스 : generatePromotionLetter(), calculateBonus()
3. ContractEmployee 클래스 : generatePromotionLetter()
4. Intern 클래스 : generatePromotionLetter()
즉, 안쓰는 메서드는 분리 시켜야 한다.
interface promotable {
void promote(double increase);
}
interface PromotionLetterGeneraTable {
void generatePromotionLetter();
}
interface BoundsCalculateTable {
double calculateBounds();
}
이처럼 각 기능별로 인터페이스를 분리하여 필요한 인터페이스만 상속받아 사용합니다.
자식 클래스는 언제나 부모 클래스 타입으로 교체할 수 있어야 함
-> 자식 객체는 부모 객체를 완전하게 대체할 수 있어야 함
다음 슬라이스에서 리스코프 치환의 원칙을 지키기 위해 인터페이스 상속을
Employee에서 받은 후 추상 메서드들을 오버라이딩하여 기본 값 설정
public class Employee implements Promotable, BoundsCalculateTable {
public String name;
public double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
@Override
public void promote(double increase) {
this.salary += increase;
}
@Override
public double calculateBounds() {
return 0;
}
인터페이스 분리 원칙에서 분리해둔 인터페이스 두개를 상속받아
Employee에 추상 메서드를 적습니다.
고수준 모듈이 저수준 모듈에 의존하지 않도록 해야 함
단, 의존 역전의 원칙은 구현체(세부 사항)가 아닌 추상화에 기반을 두기 때문에
고수준 모듈과 저수준 모듈은 모두 추상화에 의존해야 함
정책(특정 기능)을 정의하는 모듈로써 주로 비즈니스 로직을 담당하게
되며 MVC 패턴에서는 Service 계층의 인터페이스를 고수준 모듈이라고 할 수 있음
실습 코드에서는 HRDepartment 클래스가 고수준 모듈로써의 역할을 수행함
class HRDepartment {
private Promotable promotable;
public void processPromotion(Promotable promotable) {
this.promotable = promotable;
}
public void processPromotion(double increase) {
promotable.promote(increase);
}
}
정책의 세부적인 기능들을 구현하여 구체적인 작업을 수행하는 모듈
실습 코드에서는 HRDepartment 클래스를 제외한 나머지 클래스들이 저수준 모듈
@Override
public void promote(double increase) {
this.salary += increase;
}
@Override
public double calculateBounds() {
return 0;
}
class HRDepartment {
public void processPromotion(Employee employee, double increase) {
employee.promote(increase);
}
}
고수준 모듈이 저수준 모듈에 의존하지 않으며 추상화 계층에 의존하고있습니다.
만약 적용을 하게 된 정상적인 의존역전 원칙 방식은 고수준 모듈에 자료처럼 고수준 모듈이 저수준 모듈에 의존하지 않으며 추상화 계층에 의존합니다.
