diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/README.md b/놀이터(예제 코드 작성)/solid-design-pattern-sample/README.md index faa5870..77ec999 100644 --- a/놀이터(예제 코드 작성)/solid-design-pattern-sample/README.md +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/README.md @@ -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)) diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/CardPaymentService.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/CardPaymentService.kt new file mode 100644 index 0000000..e577e5f --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/CardPaymentService.kt @@ -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 + } +} diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/CashPaymentService.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/CashPaymentService.kt new file mode 100644 index 0000000..effc56b --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/CashPaymentService.kt @@ -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 + } +} diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/CouponPaymentService.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/CouponPaymentService.kt new file mode 100644 index 0000000..b4c8cc3 --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/CouponPaymentService.kt @@ -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 + } +} diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/PaymentController.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/PaymentController.kt new file mode 100644 index 0000000..0b58d51 --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/PaymentController.kt @@ -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) + } +} diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/PaymentRequestAfter.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/PaymentRequestAfter.kt new file mode 100644 index 0000000..2dd7a27 --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/PaymentRequestAfter.kt @@ -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 +) diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/PaymentServiceAfter.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/PaymentServiceAfter.kt new file mode 100644 index 0000000..a5e8956 --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/PaymentServiceAfter.kt @@ -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 +} diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/PaymentServiceFactory.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/PaymentServiceFactory.kt new file mode 100644 index 0000000..152fcf2 --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/after/PaymentServiceFactory.kt @@ -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) { + 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 +// } +// } +//} diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/before/PaymentControllerBefore.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/before/PaymentControllerBefore.kt new file mode 100644 index 0000000..0bd196a --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/before/PaymentControllerBefore.kt @@ -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) + } +} diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/before/PaymentRequestBefore.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/before/PaymentRequestBefore.kt new file mode 100644 index 0000000..b62464a --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/before/PaymentRequestBefore.kt @@ -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 +) diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/before/PaymentServiceBefore.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/before/PaymentServiceBefore.kt new file mode 100644 index 0000000..3472f93 --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/before/PaymentServiceBefore.kt @@ -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) + } +} diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/common/Payment.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/common/Payment.kt new file mode 100644 index 0000000..09451bb --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/common/Payment.kt @@ -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 +) diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/common/PaymentRepository.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/common/PaymentRepository.kt new file mode 100644 index 0000000..b6fa1f9 --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/common/PaymentRepository.kt @@ -0,0 +1,5 @@ +package com.banjjoknim.soliddesignpatternsample.solid.ocp.common + +interface PaymentRepository { + fun createPayment(amount: Int, paymentType: PaymentType): Payment +} diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/common/PaymentRepositoryStub.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/common/PaymentRepositoryStub.kt new file mode 100644 index 0000000..495f124 --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/common/PaymentRepositoryStub.kt @@ -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) + } +} diff --git a/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/common/PaymentType.kt b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/common/PaymentType.kt new file mode 100644 index 0000000..59bdf10 --- /dev/null +++ b/놀이터(예제 코드 작성)/solid-design-pattern-sample/src/main/kotlin/com/banjjoknim/soliddesignpatternsample/solid/ocp/common/PaymentType.kt @@ -0,0 +1,7 @@ +package com.banjjoknim.soliddesignpatternsample.solid.ocp.common + +enum class PaymentType { + CASH, + CARD, + COUPON +}