Template Method Pattern - The ViewModel

In this article, we'll go over the template method pattern and take a look at the Android ViewModel class as an example implementation of the pattern.

The ViewModel

The ViewModel is an application architecture component we've come to love and talk about -- VM in MVVM architecture. The Android team has packaged a ViewModel in the lifecycle library that we can subclass to model data for our views. From the docs:

A ViewModel is always created in association with a scope (a fragment or an activity) and will be retained as long as the scope is alive. E.g. if it is an Activity, until it is finished.

If the ViewModel is created in association with a scope, wouldn't it be nice to know when the scope is destroyed? Well, it is. Enter the Template Method Pattern.

The Template Method Pattern

The Template Method Pattern is a behavioral pattern in which a step in an operation is deferred to subclasses - a classic case for code reuse. The superclass defines a "hook" with some default behavior and subclasses can extend it if necessary.

Looking at the definition of the Android ViewModel, we find a method clear().

public abstract class ViewModel {
    ... // other important things

    @MainThread
    final void clear() {
        ... // omitted clean-up logic
        onCleared();
    }

    protected void onCleared() {
        // the hook
    }
}

clear() is invoked to perform clean-up logic and in the end, it calls onCleared(). (clear() is called when ViewModel scope is destroyed)

The default implementation for onCleared() is a no-op in the parent class but the protected keyword in the signature tells us that subclasses can have a go at it - and that's our hook, the template method pattern. Any code you put in the overridden method on a ViewModel subclass will be invoked when the ViewModel's scope is destroyed.

Example

Take an example where you have a subscription from some implementation of the reactive streams specification. onCleared() then becomes a suitable last-resort callback for canceling the subscription. Thanks to the template method pattern, we know it is invoked when the ViewModel is destroyed.

class PatternViewModel : ViewModel() {
    private val subscription: Subscription = ...

    override fun onCleared() {
        subscription.cancel()
    }
}

Conclusion

Design patterns make the software we write reusable, and clearer to read and maintain. The template method pattern occurs over and over again in production software and is a useful pattern to learn and use.

Happy coding.

Did you find this article valuable?

Support Charles Muchene by becoming a sponsor. Any amount is appreciated!