Шаблоны креативного дизайна в Котлине: Строитель
1. Вступление
В этой быстрой статье мы увидим, как реализовать шаблон проектирования Builder в Kotlin.
2. Образец Строителя
Шаблон Builder - это тот, который люди часто используют, но редко создают самостоятельно.
Замечательно обрабатывать построение объектов, которые могут содержать множество параметров, и когда мы хотим сделать объект неизменным после того, как построим его.
Чтобы узнать больше, ознакомьтесь с нашим руководством по Creational Design Patternshere.
3. Реализация
Kotlin предоставляет множество полезных функций, таких как именованные параметры и параметры по умолчанию,apply() иdata class, что позволяет избежать использования классической реализации шаблона Builder.
По этой причине мы увидим сначала классическую реализацию в стиле Java, а затем более короткую форму в стиле Kotlin.
3.1. Реализация в стиле Java
Давайте начнем создавать один класс -FoodOrder - который содержит поля только для чтения, поскольку мы не хотим, чтобы внешние объекты обращались к ним напрямую:
class FoodOrder private constructor(builder: FoodOrder.Builder) {
val bread: String?
val condiments: String?
val meat: String?
val fish: String?
init {
this.bread = builder.bread
this.condiments = builder.condiments
this.meat = builder.meat
this.fish = builder.fish
}
class Builder {
// builder code
}
}
Обратите внимание, чтоthe constructor is private so that only the nested Builder class can access in it.
Теперь перейдем к созданию вложенного класса, который будет использоваться для создания объектов:
class Builder {
var bread: String? = null
private set
var condiments: String? = null
private set
var meat: String? = null
private set
var fish: String? = null
private set
fun bread(bread: String) = apply { this.bread = bread }
fun condiments(condiments: String) = apply { this.condiments = condiments }
fun meat(meat: String) = apply { this.meat = meat }
fun fish(fish: String) = apply { this.fish = fish }
fun build() = FoodOrder(this)
}
Как видим,our Builder has the same fields as the outer class. For each outer field, we have a matching setter method.
Если у нас есть одно или несколько обязательных полей, вместо использования методов установки давайте сделаем конструктор, устанавливающий их.
Обратите внимание, что мы используем функциюapply для поддержки подходаfluent design.
Наконец, с помощью методаbuild мы вызываем конструкторFoodOrder.
3.2. Реализация в стиле Котлин
Чтобы в полной мере воспользоваться преимуществами Kotlin, мы должны пересмотреть некоторые лучшие практики, к которым мы привыкли в Java. Многие из них могут быть заменены лучшими альтернативами.
Давайте посмотрим, как мы можем написать идиоматический код Kotlin:
class FoodOrder private constructor(
val bread: String?,
val condiments: String?,
val meat: String?,
val fish: String?) {
data class Builder(
var bread: String? = null,
var condiments: String? = null,
var meat: String? = null,
var fish: String? = null) {
fun bread(bread: String) = apply { this.bread = bread }
fun condiments(condiments: String) = apply { this.condiments = condiments }
fun meat(meat: String) = apply { this.meat = meat }
fun fish(fish: String) = apply { this.fish = fish }
fun build() = FoodOrder(bread, condiments, meat, fish)
}
}
Kotlin comes with named and default parameters help to minimize the number of overloads и улучшите читаемость вызова функции.
Мы также можем воспользоваться структурой классов данных Kotlin, которую мы подробнее исследуем в другом руководствеhere.
Наконец, как и в реализации в стиле Java,apply() полезен для реализации свободно распространяемых сеттеров.
4. Пример использования
Вкратце, давайте посмотрим, как создавать объектыFoodOrder, используя эту реализацию шаблона Builder:
val foodOrder = FoodOrder.Builder()
.bread("white bread")
.meat("bacon")
.condiments("olive oil")
.build()
5. Заключение
Шаблон Builder решает очень распространенную проблему объектно-ориентированного программирования, заключающуюся в том, как гибко создавать неизменяемый объект без написания множества конструкторов.
Рассматривая застройщика, мы должны сосредоточиться на том, сложна ли конструкция. Если у нас слишком простые шаблоны построения, то усилия по созданию нашего гибкого объекта-строителя могут значительно превысить выгоду.
Как всегда доступен кодover on Github.