시배's Android

Kotlin | Kotlin design patterns with code example 본문

Kotlin/Kotlin

Kotlin | Kotlin design patterns with code example

si8ae 2023. 8. 13. 23:22

Singleton

"싱글톤 패턴" 클래스가 하나의 인스턴스만 가지고 있도록 보장하며, 인스턴스에 대한 전역 접근점을 제공합니다.

object SingletonExample {
    fun doSomething() {
        println("Singleton : Doing something")
    }
}

// Usage
SingletonExample.doSomething()

Decorator

"데코레이터 패턴" 동일한 클래스에서 다른 객체의 동작을 동적으로 추가할 있게 해줍니다. 다른 객체들의 동작에 영향을 주지 않고 개별 객체에 동작을 추가할 있습니다.

interface ChrismasTree {
    fun decorate() : String
}

class PineChrismasTree : ChrismasTree {
    override fun decorate() : String {
        return "Decorating pine tree"
    }
}

class Garlands(private val tree : ChrismasTree) : ChrismasTree by tree {
    override fun decorate() : String {
        return tree.decorate() + decorateWithGarlands()
    }
    
    private fun decorateWithGarlands() : String {
        return " with Garlands"
    }
}

fun main() {
    val chrismasTree = Garlands(PineChrismasTree())
    val decorateChrismasTree = chrismasTree.decorate()
    println(decorateChrismasTree)
}

Factory

클래스 기반 프로그래밍에서의 "팩토리 메서드 패턴" 정확한 클래스를 지정하지 않고 객체를 생성하기 위해 팩토리 메서드를 사용합니다. 생성자를 호출하는 대신, 객체는 인터페이스나 기본 클래스 내에서 팩토리 메서드를 호출하여 생성됩니다. 팩토리 메서드는 파생 클래스에 의해 선택적으로 구현될 있습니다.

interface Product {
    fun create()
}

class ConcreteProductA : Product {
    override fun create() = println("Product A created")
}

class ConcreteProductB : Product {
    override fun create() = println("Product B created")
}

class ProductFactory {
    fun createProduct(type : String) : Prdocut =
    	when(type){
            "A" -> ConcreteProductA()
            "B" -> ConcreteProductB()
            else -> throw IllegalArgumentException("Invalid product type")
        }
}

// Usage
val facotry = ProductFactory()
val productA = factory.createProduct("A")
productA.create()
val productB = factory.createProduct("B")
productB.create()

 

Adapter

"어댑터 패턴" 호환되지 않는 인터페이스를 가진 객체들이 함께 작동할 있도록 하기 위해 인터페이스를 다른 인터페이스로 변환하는 래퍼를 제공합니다.

interface NewPaymentProcessor {
    fun pay(amount : Double)
}

class OldPaymentProcessor {
    fun makePayment(price : Int){
        println("Payment made : $price")
    }
}

class Adapter(
	private val oldPaymentProcessor : OldPaymentProcessor 
) : NewPaymentProcessor {
    override fun pay(amount : Double) {
        oldPaymentProcessor.makePayment(amount.toInt())
    }
}

// Usage
val newPaymentProcessor : NewPaymentProcessor = Adapter(OldPaymentProcessor())
newPaymentProcessor.pay(49.99)

Observer

"옵저버 패턴" 객체 간의 종속성을 정의하여 하나의 객체의 상태가 변경될 , 해당 객체의 모든 종속 객체들이 자동으로 알림을 받고 업데이트되는 패턴입니다.

interface observer {
    fun update(message : String)
}

class ConcreteObserver(private val name : String) : Observer {
    override fun update(message : String) = println("$name received $message")
}

class Subject {
    private val observers = mutableListOf<Observer>()
    
    fun addObserver(observer : Observer) = observers.add(observer)
    
    fun removeObserver(observer : Observer) = observers.remove(observer)
    
    fun notifyObservers(message : String) {
        for(observer in observers){
            observer.update(message)
        }
    }
}

// Usage
val subject = Subject()
ConcreteObserver("Observer 1").apply { subject.addObserver(this) }
ConcreteObserver("Observer 2").apply { subject.addObserver(this) }

subject.notifyObservers("Hello observers!")

Facade

"파사드 패턴" 전체 클래스 시스템에 대한 단순화된 인터페이스를 제공하여 사용을 쉽게 만드는 패턴입니다.

class SubsystemA {
    fun operationA() {
        println("Subsystem A : Operation A")
    }
}

class SubsystemB {
    fun operationB() {
        println("Subsystem B : Operation B")
    }
}

class Facade(
	private val subsystemA : SubsystemA,
    private val subsystemB : SubsystemB
) {
    fun doSomething() {
        subsystemA.operationA()
        subsystemB.operationB()
    }
}

// Usage 
val subsystemA = SubsystemA()
val subsystemB = SubsystemB()
val facade = Facade(subsystemA, subsystemB)
facade.doSomething()

Proxy

"프록시 패턴" 다른 객체에 대한 접근을 제어하거나 기능을 추가하거나 인스턴스화를 지연시키기 위한 대리자 역할을 하는 객체를 제공하는 패턴입니다.

interface Internet {
    fun connectTo(serverHost : String)
}

class RealInternet : Internet {
    override fun connectTo(serverHost : String) {
        println("Connected to $serverHost")
    }
}

class ProxyInternet(private val realInternet : RealInternet) : Internet {
    override fun connectTo(serverHost : String){
        if(serverHost == "example.com"){
            println("Access denied. Cannot connect to $serverHost")
        }else {
            realInternet.connectTo(serverHost)
        }
    }
}

// Usage
val realInternet = RealInternet()
val proxyInternet = ProxyInternet(realInternet)

// Output : Access denied. Cannot connect to example.com
proxyInternet.connectTo("example.com")
// Output : Connected to google.com
proxyInternet.connectTo("google.com")

Strategy

"전략 패턴" 알고리즘군을 정의하고 각각을 캡슐화하여 서로 교환 가능하도록 만드는 디자인 패턴으로, 실행 중에 알고리즘을 선택할 있게 합니다.

interface PaymentStrategy{
    fun pay(amount : Double)
}

class CreditCardPayment : PaymentStrategy {
    override fun pay(amount : Double) {
        println("Paid $amount using Credit Card.")
    }
}

class PayPalPayment : PaymentStrategy {
    override fun pay(amount : Double) {
        println("Paid $amount using PayPal.")
    }
}

class ShoppingCard(private val paymentStrategy : PaymentStrategy) {
    fun checkout(amount : Double){
        paymentStrategy.pay(amount)
    }
}

// Usage 
fun main() {
	val cart = ShoppingCart(CreditCardPayment())
    cart.checkout(100.0)
    
    val anotherCart = ShoppingCart(PayPalPayment())
    anotherCart.checkout(50.0)
}

Prototype

"프로토타입 패턴" 기존 객체를 복사하여 새로운 객체를 생성하는 방식으로, 객체를 처음부터 생성하는 비용을 피할 있도록 하는 디자인 패턴입니다.

data class PrototypeProduct(val name : String)

fun main(){
    val oridinalProduct = PrototypeProduct("Original Product")
    
    val clonedProduct = originalProduct.copy()
    
    println(originalProduct)
    println(clonedProduct)
}

 

 

'Kotlin > Kotlin' 카테고리의 다른 글

Kotlin | The Big Difference Between Flows and Channels in Kotlin  (0) 2023.09.20
Kotlin | KSP vs KAPS  (0) 2023.09.20
Kotlin | Deep Dive into Sealed Interfalces  (0) 2023.09.03
Kotlin | Generic  (0) 2023.08.27
Kotlin | Flow 마스터하기  (0) 2023.08.13