Advanced Object-Oriented Programming in Kotlin

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

Lesson 02: Design Patterns

Implementing Observer 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 Observer.kts in the Starter folder for Lesson 2.

The shop could run out of products. If only a few items are left, and you have one in your cart, you should be notified if they sell out. This is a good place to implement the observer pattern for the products. This will be crucial in preventing unexpected situations, such as realizing an item is out of stock when you’ve paid for it or are about to do so.

The app shows the number of items in your cart when you run the app:

- You have 1 order items, at the cost of $24.0

Start by defining an observer interface. Any class that implements it can subscribe to a subject for updates to its state under // TODO: Create an Observer interface:

interface IObserver {
  fun update(product: Product)
}

Then, create an observable interface to define a subject that can be monitored just below the preview code:

interface IObservable {
  val observers: ArrayList<IObserver>

  fun add(observer: IObserver) {
    observers.add(observer)
  }

  fun remove(observer: IObserver) {
    observers.remove(observer)
  }

  fun sendUpdateEvent(product: Product) {
    observers.forEach { it.update(product) }
  }
}

observers keep a record of all objects that subscribe to a subject. add is for adding observers, remove is for removing observers, and sendUpdateEvent is for updating observers.

Make Products subjects and ShoppingCart an observer. This way, the cart can always stay up to date on the state of its content.

To make Product a subject, make it implement IObservable, so replace it with the following:

class Product(name: String, price: Double) : IObservable {
  override val observers: ArrayList<IObserver> = ArrayList()

  var name = name
    set(value) {
      field = value
      sendUpdateEvent(this)
    }

  var price = price
    set(value) {
      field = value
      sendUpdateEvent(this)
    }
}

After making Product observable, you updated its setter properties to trigger a notification event when they’re updated. Next, make ShoppingCart an observer:

class ShoppingCart private constructor() : IObserver {

Override update to react to notifications it receives:

override fun update(product: Product) {
  orderItems.find { it.getProduct() == product }?.product(product)
}

Make the following update to addOrderItem to make the cart listen to a product automatically each time it’s added to the cart. Below orderItems.add(orderItem), add:

orderItem.getProduct().add(this)

That’s all you need to implement an observer pattern. To test it, update the price for the product in the cart. Add the following code below // TODO: Update price of product:

skatingGloves.price = 6.0

Rerun the app:

- You have 1 order items, at the cost of $12.0

The cart has been updated with the change made to the product.

That’s all for this demo. Continue to the concluding segment.

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