Spring Framework/스프링 입문을 위한 자바 객체 지향의 원리와 이해
6장 - 스프링이 사랑한 디자인 패턴
Junuuu
2023. 4. 21. 00:01
반응형
스프링은 객체 지향의 특성과 설계 원칙을 극한까지 적용한 프레임워크입니다.
스프링을 공부하다 보면 자연스럽게 객체 지향 설계의 베스트 프렉티스, 즉 디자인 패턴을 만날 수 있습니다.
어댑터 패턴
호출당하는 쪽의 메서드를 호출하는 쪽의 코드에 대응하도록 중간에 변환기를 통해 호출하는 패턴입니다.
serviceA.runServiceA()
serviceB.runServiceB()
//위의 코드를 어댑터로 감싼다
class AdapterServiceA{
val sa1= ServiceA()
fun runService(){
sa1.runServiceA()
}
}
class AdapterServiceB{
val sb1= ServiceB()
fun runService(){
sb1.runServiceB()
}
}
// 이제 다음과 같이 같은 이름으로 호출할 수 있습니다.
AdaterServiceA.runService()
AdaterServiceB.runService()
인터페이스를 활용하여 더 개선시킬 수 있습니다.
프록시 패턴과 데코레이터 패턴의 차이
둘은 유사하지만 다음과 같이 다르다
- 데코레이터 패턴은 메서드 호출의 반환값에 변화를 준다. (반환값에 장식을 더함)
- 프록시 패턴은 제어 흐름을 조정하기 위한 목적으로 중간에 대리자를 둔다 (별도의 추가적인 로직 처리 목적)
싱글톤 패턴
- 클래스 인스턴스, 즉 객체를 하나만 만들어 사용하는 패턴
템플릿 메서드 패턴
class Dog{
fun playWithOnwer(){
println("duplicate1")
println("멍멍") -> play()
println("duplicate2")
println("duplicate3")
}
}
class Cat{
fun playWithOnwer(){
println("duplicate1")
println("야옹") // -> play()
println("duplicate2")
println("duplicate3")
}
}
//멍멍과 야옹빼고는 동일하다
//Animal이라는 추상클래스에 play()라는 추상메서드를 활용하여 중복되지 않은 부분을 구현하도록 한다.
val bolt: Animal = Dog()
val kitty: Animal = Cat()
bolt.playWithOnwer()
kitty.playWithOnwer()
상속과 추상메서드를 이용하여 상위 클래스의 견본 메서드에서 하위 클래스가 오버라이딩한 메서드를 호출하는 패턴
팩토리 메서드 패턴
- 오버라이딩된 메서드가 구현체의 객체를 반환하는 패턴
전략 패턴
interface Strategy{
fun runStrategy()
}
class StrategyGun: Strategy{
override fun runStrategy() {
println("총을 쏜다")
}
}
class StrategySword: Strategy{
override fun runStrategy() {
println("검을 휘두른다")
}
}
class Soldier{
fun runContext(strategy: Strategy){
println("전투 시작")
strategy.runStrategy()
println("전투 종료")
}
}
fun main() {
val soldier = Soldier()
soldier.runContext(StrategyGun())
soldier.runContext(StrategySword())
}
클라이언트가 전략을 생성해 전략을 실행할 콘텍스트에 주입하는 패턴
템플릿 콜백 패턴
class Soldier{
fun runContext(weapon: String){
println("전투 시작")
executeWeapon(weapon).runStrategy()
println("전투 종료")
}
fun executeWeapon(weapon: String): Strategy{
return object : Strategy {
override fun runStrategy() {
println(weapon)
}
}
}
}
fun main() {
val soldier = Soldier()
soldier.runContext("총을 쏜다")
soldier.runContext("칼을 휘두른다")
}
전략을 익명 내부 클래스로 구현한 전략 패턴