feat : SOLID - OCP 샘플 코드 구현
This commit is contained in:
@@ -17,6 +17,17 @@
|
|||||||
- 계좌에 입금할 수 있다.
|
- 계좌에 입금할 수 있다.
|
||||||
- 계좌에서 출금할 수 있다.
|
- 계좌에서 출금할 수 있다.
|
||||||
|
|
||||||
|
### OCP(Open/Closed 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))
|
- [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,20 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.after
|
||||||
|
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.Payment
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.PaymentRepository
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.PaymentType
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
class CardPaymentService(
|
||||||
|
private val paymentRepository: PaymentRepository
|
||||||
|
): PaymentServiceAfter {
|
||||||
|
override fun pay(request: PaymentRequestAfter): Payment {
|
||||||
|
println("카드 결제로 ${request.amount}원을 차감합니다.")
|
||||||
|
return paymentRepository.createPayment(request.amount, request.paymentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPaymentType(): PaymentType {
|
||||||
|
return PaymentType.CARD
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.after
|
||||||
|
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.Payment
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.PaymentRepository
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.PaymentType
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
class CashPaymentService(
|
||||||
|
private val paymentRepository: PaymentRepository
|
||||||
|
): PaymentServiceAfter {
|
||||||
|
override fun pay(request: PaymentRequestAfter): Payment {
|
||||||
|
println("현금드 결제로 ${request.amount}원을 차감합니다.")
|
||||||
|
return paymentRepository.createPayment(request.amount, request.paymentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPaymentType(): PaymentType {
|
||||||
|
return PaymentType.CASH
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.after
|
||||||
|
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.Payment
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.PaymentRepository
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.PaymentType
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
class CouponPaymentService(
|
||||||
|
private val paymentRepository: PaymentRepository
|
||||||
|
): PaymentServiceAfter {
|
||||||
|
override fun pay(request: PaymentRequestAfter): Payment {
|
||||||
|
println("쿠폰 결제는 잔고 차감이 없습니다.")
|
||||||
|
return paymentRepository.createPayment(request.amount, request.paymentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPaymentType(): PaymentType {
|
||||||
|
return PaymentType.COUPON
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.after
|
||||||
|
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.Payment
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
||||||
|
@RequestMapping("/payments")
|
||||||
|
@RestController
|
||||||
|
class PaymentController(
|
||||||
|
private val paymentServiceFactory: PaymentServiceFactory
|
||||||
|
) {
|
||||||
|
@PostMapping("with-ocp")
|
||||||
|
fun pay(request: PaymentRequestAfter): Payment {
|
||||||
|
val paymentService = paymentServiceFactory.getPaymentService(request.paymentType)
|
||||||
|
return paymentService.pay(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.after
|
||||||
|
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.PaymentType
|
||||||
|
|
||||||
|
data class PaymentRequestAfter(
|
||||||
|
val amount: Int,
|
||||||
|
val paymentType: PaymentType
|
||||||
|
)
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.after
|
||||||
|
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.Payment
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.PaymentType
|
||||||
|
|
||||||
|
interface PaymentServiceAfter {
|
||||||
|
fun pay(request: PaymentRequestAfter): Payment
|
||||||
|
|
||||||
|
fun getPaymentType(): PaymentType
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.after
|
||||||
|
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.PaymentType
|
||||||
|
import org.springframework.stereotype.Component
|
||||||
|
|
||||||
|
@Component
|
||||||
|
class PaymentServiceFactory(val paymentServices: List<PaymentServiceAfter>) {
|
||||||
|
fun getPaymentService(paymentType: PaymentType): PaymentServiceAfter {
|
||||||
|
return this.paymentServices.find { it.getPaymentType() == paymentType }
|
||||||
|
?: throw NoSuchElementException("해당 결제방식에 대한 구현이 존재하지 않습니다.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@Component
|
||||||
|
//class PaymentServiceFactory(
|
||||||
|
// private val cashPaymentService: CashPaymentService,
|
||||||
|
// private val cardPaymentService: CardPaymentService,
|
||||||
|
// private val couponPaymentService: CouponPaymentService
|
||||||
|
//) {
|
||||||
|
// fun findPaymentService(paymentType: PaymentType): PaymentServiceAfter {
|
||||||
|
// return when (paymentType) {
|
||||||
|
// PaymentType.CASH -> cashPaymentService
|
||||||
|
// PaymentType.CARD -> cardPaymentService
|
||||||
|
// PaymentType.COUPON -> couponPaymentService
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.before
|
||||||
|
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.Payment
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
||||||
|
@RequestMapping("/payments")
|
||||||
|
@RestController
|
||||||
|
class PaymentControllerBefore(
|
||||||
|
private val paymentServiceBefore: PaymentServiceBefore
|
||||||
|
) {
|
||||||
|
@PostMapping("/none-ocp")
|
||||||
|
fun pay(@RequestBody request: PaymentRequestBefore): Payment {
|
||||||
|
return paymentServiceBefore.pay(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.before
|
||||||
|
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.PaymentType
|
||||||
|
|
||||||
|
data class PaymentRequestBefore(
|
||||||
|
val amount: Int,
|
||||||
|
val type: PaymentType
|
||||||
|
)
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.before
|
||||||
|
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.Payment
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.PaymentRepository
|
||||||
|
import com.banjjoknim.soliddesignpatternsample.solid.ocp.common.PaymentType
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
|
@Service
|
||||||
|
class PaymentServiceBefore(
|
||||||
|
private val paymentRepository: PaymentRepository
|
||||||
|
) {
|
||||||
|
fun pay(request: PaymentRequestBefore): Payment {
|
||||||
|
when (request.type) {
|
||||||
|
PaymentType.CASH -> println("현금 결제로 ${request.amount}원을 차감합니다.")
|
||||||
|
PaymentType.CARD -> println("카드 결제로 ${request.amount}원을 차감합니다.")
|
||||||
|
PaymentType.COUPON -> println("쿠폰 결제는 잔고 차감이 없습니다.")
|
||||||
|
// NewPaymentType -> ...
|
||||||
|
}
|
||||||
|
return paymentRepository.createPayment(request.amount, request.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.common
|
||||||
|
|
||||||
|
import javax.persistence.Entity
|
||||||
|
import javax.persistence.Id
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
class Payment(
|
||||||
|
val amount: Int,
|
||||||
|
val type: PaymentType,
|
||||||
|
@Id
|
||||||
|
val id: Long = 0L
|
||||||
|
)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.common
|
||||||
|
|
||||||
|
interface PaymentRepository {
|
||||||
|
fun createPayment(amount: Int, paymentType: PaymentType): Payment
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.common
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
class PaymentRepositoryStub : PaymentRepository {
|
||||||
|
override fun createPayment(amount: Int, paymentType: PaymentType): Payment {
|
||||||
|
return Payment(amount = amount, type = paymentType)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.banjjoknim.soliddesignpatternsample.solid.ocp.common
|
||||||
|
|
||||||
|
enum class PaymentType {
|
||||||
|
CASH,
|
||||||
|
CARD,
|
||||||
|
COUPON
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user