feat : SOLID - LSP 샘플 코드 구현
This commit is contained in:
@@ -28,6 +28,15 @@
|
||||
- 쿠폰 결제방식을 추가한다고 가정한다.
|
||||
- 쿠폰으로 결제할 경우 잔고가 차감되지 않는다.
|
||||
|
||||
### LSP(Liskov Substitution Principle)
|
||||
|
||||
- 리스코프 치환 원칙
|
||||
- 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
|
||||
|
||||
#### 구현 요구사항
|
||||
|
||||
- 좌표를 입력하면 해당 좌표로 이동수단의 위치가 변한다.
|
||||
|
||||
## 참고자료
|
||||
|
||||
- [SOLID (객체 지향 설계)](https://ko.wikipedia.org/wiki/SOLID_(%EA%B0%9D%EC%B2%B4_%EC%A7%80%ED%96%A5_%EC%84%A4%EA%B3%84))
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.after
|
||||
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.Vehicle
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleMoveRequest
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleRepository
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleType
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Service
|
||||
class CarVehicleServiceAfter(
|
||||
private val vehicleRepository: VehicleRepository
|
||||
): VehicleServiceAfter() {
|
||||
override fun move(request: VehicleMoveRequest): Vehicle {
|
||||
println("자동차가 이동합니다.")
|
||||
val vehicle = vehicleRepository.getVehicle(request.vehicleId)
|
||||
vehicle.positionX = request.positionX
|
||||
vehicle.positionY = request.positionY
|
||||
return vehicle
|
||||
}
|
||||
|
||||
override fun vehicleType(): VehicleType {
|
||||
return VehicleType.CAR
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.after
|
||||
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.Vehicle
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleMoveRequest
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleRepository
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleType
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Service
|
||||
class PlaneVehicleServiceAfter(
|
||||
private val vehicleRepository: VehicleRepository
|
||||
): VehicleServiceAfter() {
|
||||
override fun move(request: VehicleMoveRequest): Vehicle {
|
||||
println("비행기가 이동합니다.")
|
||||
val vehicle = vehicleRepository.getVehicle(request.vehicleId)
|
||||
vehicle.positionX = request.positionX
|
||||
vehicle.positionY = request.positionY
|
||||
return vehicle
|
||||
}
|
||||
|
||||
override fun vehicleType(): VehicleType {
|
||||
return VehicleType.PLANE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.after
|
||||
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.Vehicle
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleMoveRequest
|
||||
import org.springframework.web.bind.annotation.PatchMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RequestMapping("/vehicles")
|
||||
@RestController
|
||||
class VehicleControllerAfter(
|
||||
private val vehicleServiceFactoryAfter: VehicleServiceFactoryAfter
|
||||
) {
|
||||
@PatchMapping("/with-lsp")
|
||||
fun move(@RequestBody request: VehicleMoveRequest): Vehicle {
|
||||
val vehicleServiceAfter = vehicleServiceFactoryAfter.getVehicleServiceAfter(request.vehicleType)
|
||||
return vehicleServiceAfter.move(request)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.after
|
||||
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.Vehicle
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleMoveRequest
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleType
|
||||
|
||||
abstract class VehicleServiceAfter {
|
||||
abstract fun move(request: VehicleMoveRequest): Vehicle
|
||||
|
||||
abstract fun vehicleType(): VehicleType
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.after
|
||||
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleType
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class VehicleServiceFactoryAfter(
|
||||
val vehicleServiceAfters: List<VehicleServiceAfter>
|
||||
) {
|
||||
fun getVehicleServiceAfter(vehicleType: VehicleType): VehicleServiceAfter {
|
||||
return vehicleServiceAfters.find { it.vehicleType() == vehicleType }
|
||||
?: throw NoSuchElementException("해당 이동수단에 대한 구현이 존재하지 않습니다.")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.before
|
||||
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.Vehicle
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleMoveRequest
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleRepository
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleType
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Service
|
||||
class CarVehicleServiceBefore(
|
||||
private val vehicleRepository: VehicleRepository
|
||||
) : VehicleServiceBefore(vehicleRepository) {
|
||||
override fun move(request: VehicleMoveRequest): Vehicle {
|
||||
val vehicle = vehicleRepository.getVehicle(request.vehicleId)
|
||||
vehicle.positionX += request.positionX // 하위 타입에서의 잘못된 오버라이딩!
|
||||
vehicle.positionY += request.positionY // 하위 타입에서의 잘못된 오버라이딩!
|
||||
return vehicle
|
||||
}
|
||||
|
||||
override fun vehicleType(): VehicleType {
|
||||
return VehicleType.CAR
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.before
|
||||
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.Vehicle
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleMoveRequest
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleRepository
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleType
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Service
|
||||
class PlaneVehicleServiceBefore(
|
||||
private val vehicleRepository: VehicleRepository
|
||||
) : VehicleServiceBefore(vehicleRepository) {
|
||||
override fun move(request: VehicleMoveRequest): Vehicle {
|
||||
val vehicle = vehicleRepository.getVehicle(request.vehicleId)
|
||||
vehicle.positionX -= request.positionX // 하위 타입에서의 잘못된 오버라이딩!
|
||||
vehicle.positionY -= request.positionY // 하위 타입에서의 잘못된 오버라이딩!
|
||||
return vehicle
|
||||
}
|
||||
|
||||
override fun vehicleType(): VehicleType {
|
||||
return VehicleType.PLANE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.before
|
||||
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.Vehicle
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleMoveRequest
|
||||
import org.springframework.web.bind.annotation.PatchMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RequestMapping("/vehicles")
|
||||
@RestController
|
||||
class VehicleControllerBefore(
|
||||
private val vehicleServiceFactoryBefore: VehicleServiceFactoryBefore
|
||||
) {
|
||||
@PatchMapping("/none-lsp")
|
||||
fun move(@RequestBody request: VehicleMoveRequest): Vehicle {
|
||||
val vehicleServiceBefore = vehicleServiceFactoryBefore.getVehicleServiceBefore(request.vehicleType)
|
||||
return vehicleServiceBefore.move(request)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.before
|
||||
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.Vehicle
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleMoveRequest
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleRepository
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleType
|
||||
|
||||
abstract class VehicleServiceBefore(
|
||||
private val vehicleRepository: VehicleRepository
|
||||
) {
|
||||
open fun move(request: VehicleMoveRequest): Vehicle {
|
||||
val vehicle = vehicleRepository.getVehicle(request.vehicleId)
|
||||
vehicle.positionX = request.positionX
|
||||
vehicle.positionY = request.positionY
|
||||
return vehicle
|
||||
}
|
||||
|
||||
abstract fun vehicleType(): VehicleType
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.before
|
||||
|
||||
import com.banjjoknim.soliddesignpatternsample.solid.lsp.common.VehicleType
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class VehicleServiceFactoryBefore(
|
||||
val vehicleServiceBefores: List<VehicleServiceBefore>
|
||||
) {
|
||||
fun getVehicleServiceBefore(vehicleType: VehicleType): VehicleServiceBefore {
|
||||
return vehicleServiceBefores.find { it.vehicleType() == vehicleType }
|
||||
?: throw NoSuchElementException("해당 이동수단에 대한 구현이 존재하지 않습니다.")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.common
|
||||
|
||||
import javax.persistence.Entity
|
||||
import javax.persistence.Id
|
||||
|
||||
@Entity
|
||||
class Vehicle(
|
||||
var positionX: Int = 0,
|
||||
var positionY: Int = 0,
|
||||
@Id
|
||||
val id: Long = 0L
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.common
|
||||
|
||||
data class VehicleMoveRequest(
|
||||
val vehicleId: Long,
|
||||
val positionX: Int,
|
||||
val positionY: Int,
|
||||
val vehicleType: VehicleType
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.common
|
||||
|
||||
interface VehicleRepository {
|
||||
fun getVehicle(vehicleId: Long): Vehicle
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.common
|
||||
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
class VehicleRepositoryStub : VehicleRepository {
|
||||
override fun getVehicle(vehicleId: Long): Vehicle {
|
||||
return Vehicle(id = vehicleId)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.banjjoknim.soliddesignpatternsample.solid.lsp.common
|
||||
|
||||
enum class VehicleType {
|
||||
CAR,
|
||||
PLANE
|
||||
}
|
||||
Reference in New Issue
Block a user