객체 지향 프로그래밍- SOLID

2024. 5. 23. 11:19스프링

반응형

객체 지향 특징

- 추상화

- 캡슐화

- 상속

- 다형성(유연하고 변경이 쉬움)

 

객체 지향 프로그래밍은 여러 개의 독립된 '객체'으로 되어 있다. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다. 객체는 자바에서 class라고 생각하면 된다. 

 

객체 지향 특징 중에서 다형성이 중요!!

 

다형성

예를들어 자동차라는 역할이 있다. 이 역할을 수행하는 자동차 k3, 아반떼, 테슬라가 있다. 운전자는 어떠한 자동차를 타든 운전을 할 수 있다. 자동차를 다른것으로 바꿔도 운전을 할 수 있는거다. 여기서 자동차 역할은 interface이고, 이 interface를 구현한 객체(클래스)가 k3, 아반떼, 테슬라이다. 이렇게 어떠한 자동차 객체로든 바꿀 수 있게 변경이 쉽고 유연한 이유는 다형성 때문이다. 

 

SOLID

- SRP(single responsibility principle) 단일 책임 원칙

  변경이 있을때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것

  예를들어 클래스나 메소드가 너무 많은 기능을 담당하고 있으면 그 기능을 수정하거나 변경할 때 더 많이 손이간다. 따라    서 하나의 메소드에는 하나의 기능을 담당하게 해서 나중에 변경이 있더라도 손이 덜 가게 하는게 단일책임원칙이다. 

 

- OCP(open/closed principle) 개방-폐쇄 원칙

  확장에는 열려 있으나 변경에는 닫혀 있어야 한다. 예를들어 자동차 역할 인터페이스에 대한 구현된 다른 자동차를 만든    다고 하자. 새로운 아우디 자동차 객체를 만들었다고 해서 기존 코드에 변경이 생기지 않는다. 이렇게 새로운 구현 객체      에는 열려 있으나 코드의 변경에는 닫혀있다.

public class Car {
	public void howMuch(String car){
    	if(car.equals("audi"){//아우디
        	System.out.println("일억천만원");
        }else if(car.equals("Volkswagen"){//폭스바겐
        	System.out.println("육천만원");
        }
    }

}

// 위와 같이 Car 객체가 있다고 하자. Car의 howmuch 메소드로 자동차의 가격을 알 수 있게 한다.
// 만약 아우디, 폭스바겐 말고 페라리 라는 자동차 가격을 추가하려면 
// else if문으로 페라리도 추가 해줘야한다.
/*
	if(car.equals("Audi"){//아우디
        System.out.println("일억천만원");
    }else if(car.equals("Volkswagen"){//폭스바겐
        System.out.println("육천만원");
    }else if(car.equals("Ferrari"){//페라리
        System.out.println("2억원");
    }
*/

// 이렇게 새로운 자동차 가격을 추가할때마다 소스를 수정해줘야 한다. 


// 위의 소스를 OCP 로 바꿔보겠다.

//인터페이스나 추상 클래스로 추상적이게 만들어준다.
public interface Car {
	public void howMuch();

}

//인터페이스나 추상 클래스를 구현하여 새로운 객체를 만들어준다.(확장에는 열려있음)

public class Audi implements Car{
	@Override
    public void howMuch(){
    	System.out.println("일억천만원");
    }
}

public class Volkswagen implements Car{
	@Override
    public void howMuch(){
    	System.out.println("육천만원");
    }
}

//만약 현대 자동차를 추가하려면 따로 소스를 수정할 필요없이 그냥 새로운 객체를 추가해주면 된다.
//OCP는 이렇게 객체의 직접적인 소스 수정에는 닫혀있다.

public class Hyunda implements Car{
	@Override
    public void howMuch(){
    	System.out.println("팔천만원");
    }
}

 

- LSP(liskov substitution principle) 리스코프 치환 원칙

  프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다. 자동차 인터      페이스에 대한 구현체에서 각 자동차 객체에 있는 브레이크 메소드는 멈추는 동작을 수행해야 하는데 앞으로 가거나 뒤      로 가면 안된다. 

 

- ISP(interface segregation principle)인터페이스 분리 원칙

  특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.

  예를들어 사용자 인터페이스 하나보다 운전자 인터페이스, 정비사 인터페이스로 나누는 것이 인터페이스가 명확해지고,    대체 가능성이 높아진다.

참고) 하지만 너무 많은 인터페이스 사용은 비용이 발생한다. 예를들어 자동차 역할 인터페이스가 어떤 구현 객체를 사용했는지 알기 위해서 일일히 확인해야함

 

- DIP(dependency inversion principle) 의존관계 역전 원칙

  클래스 객체에서 다른 객체를 의존할때 인터페이스나 추상클래스와 같이 상위 클래스를 의존해야지 구현체를 의존하면      안된다. 만약 구현체를 의존하면 다른 구현체로 변경할때 소스를 수정하거나 변경 해줘야 한다. 이렇게 하위 구현체보다    상위 객체를 의존하는걸 의존관계 역전 원칙 이라고 한다.  

 

//인터페이스
public interface Animal {
  String cry();
}

//인터페이스 구현
public class Duck implements Animal {
  @Override
  public String cry() {
    return "괙괙";
  }
}

public class Tiger implements Animal {
  @Override
  public String cry() {
    return "어흥";
  }
}


//Duck이나 Tiger에 의존하지 않고 Animal에 의존하여 Tiger나 Animal로 수정되어도 소스를 수정할 필요없다.
public class AnimalService {

  private Animal animal;

  public AnimalService(Animal animal) {
    this.animal = animal;
  }

  public String cry() {
    return animal.cry();
  }

}

 

 

스프링은 DI 컨테이너를 제공해서 OCP와 DIP를 가능하게 지원한다.

 

 

 

 

 

 

 

반응형

'스프링' 카테고리의 다른 글

스프링 spring  (0) 2024.05.16
스프링 AOP  (0) 2024.05.16
스프링 jdbc 템플릿  (0) 2024.05.16
스프링부트 테스트  (0) 2024.05.14
DI 주입 방법  (0) 2024.05.14