Template method

Some lazy people make art out of their laziness. Take me for example. Here's my daily schedule:

  1. 8:00–9:00: Arrive at the office
  2. 9:0010:00: Drink coffee
  3. 10:0012:00: Attend some meetings or review code
  4. 12:0013:00: Go out for lunch
  5. 13:0016:00: Attend some meetings or review code
  6. 16:00: Sneak out home

As you can see, some of the parts of the schedule never change, and some do. At first, I thought I could decorate my changing schedule with that setup and teardown logic, which happens before and after. But then there's lunch, which is holy for architects and happens in between

Java is pretty clear on what you should do. First, you create an abstract class. All methods that you want to implement by yourself you mark as private:

abstract class DayRoutine {
private fun arriveToWork() {
println("Hi boss! I appear in the office sometimes!")
}

private fun drinkCoffee() {
println("Coffee is delicious today")
}

...

private fun goToLunch() {
println("Hamburger and chips, please!")
}

...

private fun goHome() {
// Very important no one notices me
println()
}

...
}

For all methods that are changing from day to day, you define an abstract:

abstract class DayRoutine {
...
abstract fun doBeforeLunch()
...
abstract fun doAfterLunch()
...
}

If you allow the changing of a method, but want to provide a default implementation, you leave it public:

abstract class DayRoutine {
...
open fun bossHook() {
// Hope he doesn't hook me there
}
...
}

And finally, you have a method that executes your algorithm. It's final by default:

abstract class DayRoutine {
...
fun runSchedule() {
arriveToWork()
drinkCoffee()
doAfterLunch()
goToLunch()
doAfterLunch()
goHome()
}
}

If we now want to have a schedule for Monday, we simply implement the missing parts:

class MondaySchedule : DayRoutine() {
override fun doBeforeLunch() {
println("Some pointless meeting")
println("Code review. What this does?")
}

override fun doAfterLunch() {
println("Meeting with Ralf")
println("Telling jokes to other architects")
}

override fun bossHook() {
println("Hey, can I have you for a sec in my office?")
}
}

What does Kotlin add on top of that? What it usually does—conciseness. As we've seen previously, this can be achieved through functions.

We have three moving parts—two mandatory activities (the software architect must do something before and after lunch) and one optional (the boss may stop him before he sneaks off home or not):

fun runSchedule(beforeLunch: ()->Unit,
afterLunch: ()->Unit,
bossHook: (()->Unit)? = fun() { println() }) {
...
}

We'll have a function that accepts up to three other functions as its arguments. The first two are mandatory, and the third may not be supplied at all, or assigned with null to explicitly state that we don't want that function to happen:

fun runSchedule(...) {
...
arriveToWork()
drinkCoffee()
beforeLunch()
goToLunch()
afterLunch()
bossHook?.let { it() }
goHome()
}

Inside this function, we'll have our algorithm. Invocations of beforeLunch() and afterLunch() should be clear; after all, those are the functions that are passed to us as arguments. The third one, bossHook, may be null, so we execute it only if it's not: ?.let { it() }.

But what about the other functions, those we want to always implement by ourselves? Kotlin has a notion of local functions. Those are functions that reside in other functions:

fun runSchedule(...) {
fun arriveToWork(){
println("How are you all?")
}

val drinkCoffee = { println("Did someone left the milk out?") }

fun goToLunch() = println("I would like something italian")

val goHome = fun () {
println("Finally some rest")
}

arriveToWork()
drinkCoffee()
...
goToLunch()
...
goHome()
}

Those are all valid ways to declare a local function. No matter how you define them, they're invoked in the same way.

We're left with the same result, as you can see. Define the algorithm structure, but let others decide what to do at some points: that's what the Template Method is all about.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.123.34