diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/chainofresposibility/AuthenticationHeader.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/chainofresposibility/AuthenticationHeader.kt new file mode 100644 index 0000000..ba673a8 --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/chainofresposibility/AuthenticationHeader.kt @@ -0,0 +1,8 @@ +package com.example.algorithmstudy.pattern.behavoiral.chainofresposibility + +class AuthenticationHeader(val token: String?, var next: HandlerChain? = null) : HandlerChain { + override fun addHeader(inputHeader: String): String = + "$inputHeader\nAuthorization : $token".let { + next?.addHeader(it) ?: it + } +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/chainofresposibility/BodyPayloadHeader.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/chainofresposibility/BodyPayloadHeader.kt new file mode 100644 index 0000000..db11b14 --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/chainofresposibility/BodyPayloadHeader.kt @@ -0,0 +1,8 @@ +package com.example.algorithmstudy.pattern.behavoiral.chainofresposibility + +class BodyPayloadHeader(val body: String?, var next: HandlerChain? = null) : HandlerChain { + override fun addHeader(inputHeader: String): String = + "$inputHeader\nContentType : $body".let { + next?.addHeader(it) ?: it + } +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/chainofresposibility/ContentTypeHeader.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/chainofresposibility/ContentTypeHeader.kt new file mode 100644 index 0000000..aefd053 --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/chainofresposibility/ContentTypeHeader.kt @@ -0,0 +1,8 @@ +package com.example.algorithmstudy.pattern.behavoiral.chainofresposibility + +class ContentTypeHeader(val contentType: String?, var next: HandlerChain? = null) : HandlerChain { + override fun addHeader(inputHeader: String): String = + "$inputHeader\nContentType : $contentType".let { + next?.addHeader(it) ?: it + } +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/chainofresposibility/HandlerChain.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/chainofresposibility/HandlerChain.kt new file mode 100644 index 0000000..9a956b4 --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/chainofresposibility/HandlerChain.kt @@ -0,0 +1,5 @@ +package com.example.algorithmstudy.pattern.behavoiral.chainofresposibility + +interface HandlerChain { + fun addHeader(inputHeader: String): String +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/ComponentA.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/ComponentA.kt new file mode 100644 index 0000000..c576c9d --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/ComponentA.kt @@ -0,0 +1,7 @@ +package com.example.algorithmstudy.pattern.behavoiral.mediator + +class ComponentA(private val mediator: Mediator) { + fun operationA() { + mediator.method(this, "arg A") + } +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/ComponentB.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/ComponentB.kt new file mode 100644 index 0000000..c3cb1ba --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/ComponentB.kt @@ -0,0 +1,7 @@ +package com.example.algorithmstudy.pattern.behavoiral.mediator + +class ComponentB(private val mediator: Mediator) { + fun operationB() { + mediator.method(this, "arg B") + } +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/ComponentC.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/ComponentC.kt new file mode 100644 index 0000000..dc7e66c --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/ComponentC.kt @@ -0,0 +1,7 @@ +package com.example.algorithmstudy.pattern.behavoiral.mediator + +class ComponentC(private val mediator: Mediator) { + fun operationC() { + mediator.method(this, "arg C") + } +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/ConcreteMediator.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/ConcreteMediator.kt new file mode 100644 index 0000000..8ea38ec --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/ConcreteMediator.kt @@ -0,0 +1,11 @@ +package com.example.algorithmstudy.pattern.behavoiral.mediator + +class ConcreteMediator : Mediator { + override fun method(sender: Any, args: Any?) { + when (sender) { + is ComponentA -> println("arg from A : $args") + is ComponentB -> println("arg from B : $args") + is ComponentC -> println("arg from C : $args") + } + } +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/Mediator.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/Mediator.kt new file mode 100644 index 0000000..ffb7f84 --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/mediator/Mediator.kt @@ -0,0 +1,8 @@ +package com.example.algorithmstudy.pattern.behavoiral.mediator + +/** + * ref : https://asvid.github.io/kotlin_mediator_pattern + */ +interface Mediator { + fun method(sender: Any, args: Any? = null) +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/observer/IObservable.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/observer/IObservable.kt new file mode 100644 index 0000000..9309dce --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/observer/IObservable.kt @@ -0,0 +1,17 @@ +package com.example.algorithmstudy.pattern.behavoiral.observer + +interface IObservable { + val observers: ArrayList + + fun add(observer: IObserver) { + observers.add(observer) + } + + fun remove(observer: IObserver) { + observers.remove(observer) + } + + fun sendUpdateEvent() { + observers.forEach { it.update() } + } +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/observer/IObserver.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/observer/IObserver.kt new file mode 100644 index 0000000..45ca699 --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/observer/IObserver.kt @@ -0,0 +1,8 @@ +package com.example.algorithmstudy.pattern.behavoiral.observer + +/** + * ref : https://www.baeldung.com/kotlin/observer-pattern + */ +interface IObserver { + fun update() +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/observer/NewsLetter.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/observer/NewsLetter.kt new file mode 100644 index 0000000..092f83b --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/observer/NewsLetter.kt @@ -0,0 +1,11 @@ +package com.example.algorithmstudy.pattern.behavoiral.observer + +class NewsLetter : IObservable { + override val observers: ArrayList = ArrayList() + + var newestArticleUrl = "" + set(value) { + field = value + sendUpdateEvent() + } +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/observer/NewsReader.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/observer/NewsReader.kt new file mode 100644 index 0000000..505b5f8 --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/observer/NewsReader.kt @@ -0,0 +1,7 @@ +package com.example.algorithmstudy.pattern.behavoiral.observer + +class NewsReader(private var newsLetter: NewsLetter) : IObserver { + override fun update() { + println("New article : ${newsLetter.newestArticleUrl}") + } +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/templatemethod/Americano.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/templatemethod/Americano.kt new file mode 100644 index 0000000..771955d --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/templatemethod/Americano.kt @@ -0,0 +1,5 @@ +package com.example.algorithmstudy.pattern.behavoiral.templatemethod + +class Americano : Drink() { + override fun addIngredient() = println("Adding 2 shots of espresso") +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/templatemethod/Drink.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/templatemethod/Drink.kt new file mode 100644 index 0000000..0ad55d9 --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/templatemethod/Drink.kt @@ -0,0 +1,25 @@ +package com.example.algorithmstudy.pattern.behavoiral.templatemethod + +/** + * reference : + * - http://www.devll.org/blog/2020/kotlin/template-method-pattern.html + * - https://kimchanjung.github.io/design-pattern/2020/05/28/template-method-pattern/ + */ +abstract class Drink { + fun prepareDrink() { + println("prepare ${this.javaClass.simpleName}") + + boilWater() + addIngredient() + fillWaterInCup() + + println("Finished preparing drink\n") + } + + // 템플릿 메소드 : 각 구현 요소에 따라 달라지는 부분 + protected abstract fun addIngredient() + + // 각 구현 요소들이 공통으로 사용하는 부분 + private fun boilWater() = println("Boil water") + private fun fillWaterInCup() = println("Fill cup with hot water") +} diff --git a/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/templatemethod/OrangeAde.kt b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/templatemethod/OrangeAde.kt new file mode 100644 index 0000000..f96437b --- /dev/null +++ b/app/src/main/java/com/example/algorithmstudy/pattern/behavoiral/templatemethod/OrangeAde.kt @@ -0,0 +1,5 @@ +package com.example.algorithmstudy.pattern.behavoiral.templatemethod + +class OrangeAde : Drink() { + override fun addIngredient() = println("Adding orange") +} diff --git a/app/src/test/java/com/example/algorithmstudy/design_pattern/ChainOfResponsibilityTest.kt b/app/src/test/java/com/example/algorithmstudy/design_pattern/ChainOfResponsibilityTest.kt new file mode 100644 index 0000000..a5f0026 --- /dev/null +++ b/app/src/test/java/com/example/algorithmstudy/design_pattern/ChainOfResponsibilityTest.kt @@ -0,0 +1,31 @@ +package com.example.algorithmstudy.design_pattern + +import com.example.algorithmstudy.pattern.behavoiral.chainofresposibility.AuthenticationHeader +import com.example.algorithmstudy.pattern.behavoiral.chainofresposibility.BodyPayloadHeader +import com.example.algorithmstudy.pattern.behavoiral.chainofresposibility.ContentTypeHeader +import org.junit.Test + +/** + * ChainOfResponsibility 패턴 + * + * - https://medium.com/@catalinstefan/chain-of-responsibility-design-pattern-in-kotlin-b62f86be274f + * - 체인 형태로 이어 호출을 해야 하는 요구사항에서, 각 호출 단계별로 호출의 유효성과 오류를 확인 가능하며, 이상이 없는 경우 다음 체인까지 진행하도록 하는 패턴 + */ +class ChainOfResponsibilityTest { + + @Test + fun testChainOfResponsibility() { + val authenticationHeader = AuthenticationHeader("111") + val contentTypeHeader = ContentTypeHeader("json") + val bodyPayloadHdader = BodyPayloadHeader("Body: body") + + authenticationHeader.next = contentTypeHeader + contentTypeHeader.next = bodyPayloadHdader + + val messageWithAuth = authenticationHeader.addHeader("HEADERS WITH AUTHENTICATION") + println(messageWithAuth) + + val messageWithoutAuth = contentTypeHeader.addHeader("HEADERS WITH AUTHENTICATION") + println(messageWithoutAuth) + } +} diff --git a/app/src/test/java/com/example/algorithmstudy/design_pattern/MediatorTest.kt b/app/src/test/java/com/example/algorithmstudy/design_pattern/MediatorTest.kt new file mode 100644 index 0000000..58c8393 --- /dev/null +++ b/app/src/test/java/com/example/algorithmstudy/design_pattern/MediatorTest.kt @@ -0,0 +1,29 @@ +package com.example.algorithmstudy.design_pattern + +import com.example.algorithmstudy.pattern.behavoiral.mediator.ComponentA +import com.example.algorithmstudy.pattern.behavoiral.mediator.ComponentB +import com.example.algorithmstudy.pattern.behavoiral.mediator.ComponentC +import com.example.algorithmstudy.pattern.behavoiral.mediator.ConcreteMediator +import org.junit.Test + +/** + * Mediator Pattern + * + * - 컴포넌트들은 Mediator를 reference로 가지며, 서로가 소통할 일은 없음 + * - Mediator는 각 컴포넌트들을 판단해 각각 필요한 동작을 수행하도록 조정함(말대로 중재자) + */ +class MediatorTest { + + @Test + fun mediatorTest() { + ConcreteMediator().apply { + val componentA = ComponentA(this) + val componentB = ComponentB(this) + val componentC = ComponentC(this) + + method(componentA) + method(componentB) + method(componentC) + } + } +} diff --git a/app/src/test/java/com/example/algorithmstudy/design_pattern/ObserverTest.kt b/app/src/test/java/com/example/algorithmstudy/design_pattern/ObserverTest.kt new file mode 100644 index 0000000..53dd482 --- /dev/null +++ b/app/src/test/java/com/example/algorithmstudy/design_pattern/ObserverTest.kt @@ -0,0 +1,22 @@ +package com.example.algorithmstudy.design_pattern + +import com.example.algorithmstudy.pattern.behavoiral.observer.NewsLetter +import com.example.algorithmstudy.pattern.behavoiral.observer.NewsReader +import org.junit.Test + +/** + * Observer Pattern test + */ +class ObserverTest { + + @Test + fun TestObserverPattern() { + val newsLetter = NewsLetter() + val reader = NewsReader(newsLetter) + + newsLetter.add(reader) + newsLetter.newestArticleUrl = "news 1" + newsLetter.newestArticleUrl = "news 2" + newsLetter.newestArticleUrl = "news 3" + } +} diff --git a/app/src/test/java/com/example/algorithmstudy/design_pattern/TemplateMethodTest.kt b/app/src/test/java/com/example/algorithmstudy/design_pattern/TemplateMethodTest.kt new file mode 100644 index 0000000..2cffcd0 --- /dev/null +++ b/app/src/test/java/com/example/algorithmstudy/design_pattern/TemplateMethodTest.kt @@ -0,0 +1,22 @@ +package com.example.algorithmstudy.design_pattern + +import com.example.algorithmstudy.pattern.behavoiral.templatemethod.Americano +import com.example.algorithmstudy.pattern.behavoiral.templatemethod.OrangeAde +import org.junit.Test + +/** + * TemplateMethod 패턴 + * + * - 공통된 function들은 함께 사용하되, 각 구현 요소별로 다르게 수행할 function을 각각 정의해 사용 가능한 패턴 + */ +class TemplateMethodTest { + + @Test + fun testTemplateMethod() { + val americano = Americano() + val orangeAde = OrangeAde() + + americano.prepareDrink() + orangeAde.prepareDrink() + } +}