Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 30 additions & 24 deletions src/main/kotlin/ru/otus/homework/homework/Coffee.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,38 @@ class SimpleCoffee : Coffee {
override fun description() = "Простой кофе"
}

class MilkDecorator(private val coffee: Coffee) : Coffee {
override fun cost(): Int {
TODO("Not yet implemented")
}

override fun description(): String {
TODO("Not yet implemented")
}
}
/**
* Базовый декоратор: хранит оборачиваемый напиток и знает,
* как добавить к нему стоимость и название ингредиента.
* Наследникам остается только объявить свою добавку.
*/
abstract class CoffeeDecorator(private val coffee: Coffee) : Coffee {
/**
* Стоимость добавки в копейках
*/
protected abstract val additionalCost: Int

/**
* Название добавки для описания напитка
*/
protected abstract val ingredient: String

override fun cost(): Int = coffee.cost() + additionalCost

class SugarDecorator(private val coffee: Coffee) : Coffee {
override fun cost(): Int {
TODO("Not yet implemented")
}
override fun description(): String = "${coffee.description()}, $ingredient"
}

override fun description(): String {
TODO("Not yet implemented")
}
class MilkDecorator(coffee: Coffee) : CoffeeDecorator(coffee) {
override val additionalCost = 50
override val ingredient = "молоко"
}

class VanillaDecorator(private val coffee: Coffee) : Coffee {
override fun cost(): Int {
TODO("Not yet implemented")
}
class SugarDecorator(coffee: Coffee) : CoffeeDecorator(coffee) {
override val additionalCost = 20
override val ingredient = "сахар"
}

override fun description(): String {
TODO("Not yet implemented")
}
}
class VanillaDecorator(coffee: Coffee) : CoffeeDecorator(coffee) {
override val additionalCost = 70
override val ingredient = "ваниль"
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import kotlin.reflect.KProperty
/**
* Delegate that allows to set non-empty string value
*/
class NonEmptyStringDelegate() {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
TODO("Implement `getValue` function")
}
class NonEmptyStringDelegate(private var value: String = "") {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String = value

operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: String) {
TODO("Implement `setValue` function")
if (newValue.isNotBlank()) {
value = newValue
}
}
}
}
73 changes: 69 additions & 4 deletions src/main/kotlin/ru/otus/homework/homework/UserProfile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

package ru.otus.homework.homework

import kotlin.properties.Delegates

/**
* Профиль пользователя
*/
Expand Down Expand Up @@ -36,9 +38,8 @@ interface UserProfile {
/**
* Creates user profile with logging
*/
fun createWithLogging(fullName: String, email: String): UserProfile.Logging {
TODO("Implement `createWithLogging` function")
}
fun createWithLogging(fullName: String, email: String): UserProfile.Logging =
LoggingProfileImplementation(create(fullName, email))
}
}

Expand All @@ -50,4 +51,68 @@ private val emailRegex = Regex("^[A-Za-z](.*)([@])(.+)(\\.)(.+)")
/**
* Реализация простого [UserProfile].
*/
private class ProfileImplementation(override var fullName: String, override var email: String): UserProfile
private class ProfileImplementation(fullName: String, email: String) : UserProfile {

override var fullName: String by NonEmptyStringDelegate(fullName)

override var email: String by Delegates.vetoable(email) { _, _, newValue ->
emailRegex.matches(newValue)
}
}

/**
* Журнал с возможностью записи. Приватный интерфейс: наружу, через [WithLogging],
* журнал доступен только на чтение.
*/
private interface LogWriter : WithLogging {
fun record(property: String, oldValue: String, newValue: String)
}

/**
* Журнал изменений. Отдельный класс, чтобы профиль мог делегировать ему [LogWriter].
*/
private class LogRecorder : LogWriter {
private val entries = mutableListOf<String>()

override fun getLog(): List<String> = entries.toList()

override fun record(property: String, oldValue: String, newValue: String) {
entries += "Changing `$property` from '$oldValue' to '$newValue'"
}
}

/**
* Профиль с логированием: оборачивает готовый [UserProfile] и пишет в журнал
* каждое реально произошедшее изменение свойства.
*/
private class LoggingProfileImplementation(
private val profile: UserProfile,
private val logRecorder: LogRecorder = LogRecorder(),
) : UserProfile.Logging, LogWriter by logRecorder {

override var fullName: String
get() = profile.fullName
set(value) {
val oldValue = profile.fullName
profile.fullName = value
logIfChanged("fullName", oldValue, profile.fullName)
}

override var email: String
get() = profile.email
set(value) {
val oldValue = profile.email
profile.email = value
logIfChanged("email", oldValue, profile.email)
}

/**
* Пишет в журнал, только если значение действительно изменилось:
* делегаты [UserProfile] молча отклоняют некорректные значения.
*/
private fun logIfChanged(property: String, oldValue: String, newValue: String) {
if (newValue != oldValue) {
record(property, oldValue, newValue)
}
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/ru/otus/homework/homework/WithLogging.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ interface WithLogging {
* Текущие записи журнала
*/
fun getLog(): List<String>
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/ru/otus/homework/homework/processList.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ inline fun processList(list: List<Int>, action: (Int) -> Unit) {

fun skipThreeAndPrint(list: List<Int>) {
processList(list) {
if (it == 3) return
if (it == 3) return@processList
println("Processing $it")
}
}