Advanced Object-Oriented Programming in Kotlin

May 22 2024 · Kotlin 1.9, Android 14, Kotlin Playground

Lesson 02: Design Patterns

Implementing Factory Pattern

Episode complete

Play next episode

Next
Transcript

Start by opening the Kotlin playground in your browser. Download the course material from the GitHub link at the side of the video. Copy and paste the code from Factory.kts in the Starter folder for Lesson 2.

One common action in an e-commerce app is payments. An e-commerce app usually accepts different modes of payment. Each will have its own way of initializing and processing payment requests internally. In this demo, you’ll employ the factory pattern to create the requested payment processor.

Start by creating a payment processor interface below // TODO: Create a payment processor:

interface PaymentProcessor {
  fun processPayment(amount: Double)
}

This defines what makes a payment processor in the app. To be a payment processor, you have to implement this interface. Create two payment processors below the PaymentProcessor interface, one for credit card and the other for PayPal:

// Concrete implementation of PaymentProcessor
class CreditCardProcessor : PaymentProcessor {
  override fun processPayment(amount: Double) {
    println("Processing credit card payment of $$amount.")
    // Additional logic specific to credit card processing
  }
}

// Another concrete implementation of PaymentProcessor
class PayPalProcessor : PaymentProcessor {
  override fun processPayment(amount: Double) {
    println("Processing PayPal payment of $$amount.")
    // Additional logic specific to PayPal processing
  }
}

Take note of how concrete classes provide the implementation for a payment processor. Now, create the factory class that’ll produce these defined payment processors. Add the following code below PayPalProcessor:

interface PaymentProcessorFactory {
  fun createPaymentProcessor(): PaymentProcessor
}

You could’ve made the factory a concrete implementation too. But, making it an interface makes it flexible — so you can easily add new processors in the future.

To use PaymentProcessorFactory, create concrete implementations below PaymentProcessorFactory:

// Concrete implementation of PaymentProcessorFactory for Credit Card
class CreditCardProcessorFactory : PaymentProcessorFactory {
  override fun createPaymentProcessor(): PaymentProcessor {
    return CreditCardProcessor()
  }
}

// Concrete implementation of PaymentProcessorFactory for PayPal
class PayPalProcessorFactory : PaymentProcessorFactory {
  override fun createPaymentProcessor(): PaymentProcessor {
    return PayPalProcessor()
   }
}

Just like you defined an interface for what a payment processor should be, you defined an interface for what a factory for a payment processor should be. This brings better separation of concerns, enhances testability, and makes the code scale easily without affecting other classes.

In main() function, create a flag below // TODO: Add payment option flag to check whether or not payment is by credit card. If it’s not, it defaults to PayPal:

val customerPayingWithCC = false

Create a payment processing factory based on the flag:

// Customer wants to use CC
val paymentProcessorFactory = if (customerPayingWithCC) {
  CreditCardProcessorFactory()
} else {
  PayPalProcessorFactory()
}

Finally, create the appropriate payment processor to handle payment. Add the following snippet below the previous one:

val paymentProcessor: PaymentProcessor = paymentProcessorFactory.createPaymentProcessor()
paymentProcessor.processPayment(cart.getTotalCostOfItems())

Rerun the app:

- You have 4 order items, at the cost of $874.0
Processing PayPal payment of $874.0.

It shows that PayPal processed the payment. Make customerPayingWithCC = true and rerun the app:

- You have 4 order items, at the cost of $874.0
Processing credit card payment of $874.0.

This time, the credit card payment processor processed the payment.

That’s all for the factory pattern. Continue to the final design pattern in this lesson, the observer.

See forum comments
Cinema mode Download course materials from Github
Previous: Learning Factory Pattern Next: Learning Observer Pattern