🗒 Задача¶
Реализовать класс работы форума (Forum). Для реализации создай дополнительные классы для сущностей “Член форума” (с полями userId и userName) и “Сообщение форума” (с полями authorId и message).
Примени паттерн “Строитель” для создания пользователей и сообщений форума. Напрямую объекты не создаются, логика должна быть инкапсулирована внутри методов класса.
-
createNewUser() создает новых пользователей, принимая имя пользователя. Метод сохраняет нового пользователя в общий список и одновременно возвращает новый объект. Генерация id-шников новых пользователей происходит внутри;
-
createNewMessage() создает сообщения, принимая id пользователя. Сообщения создаются только если такой пользователь есть на форуме;
-
printThread() печатает в консоль все сообщения добавленные на форум в формате:
автор: сообщение автор: сообщение
Создай экземпляр Forum и продемонстрируй его работу, добавив двух пользователей и по два сообщения от каждого пользователя.
❌ Ошибки¶
-
для генерации id используется random — лучше использовать инкремент
-
используют readln внутри классов User и Message — нужно выносить, чтобы было более универсально
✏️ Комментарии¶
Запрашивать данные тут не нужно, эту логику если и делать, то во вне форума. Тогда класс будет более универсальным, не привязанным к консоли. Могли бы использовать его и для Андройд приложения потом к примеру.
Тут для создания User должны использоваться параметры из метода newUser(), у класса User() должно быть поле id.
Давай полностью инкапсулируем метод создания пользователей. Чтобы передавать в метод только данные о пользователе (кроме id). Это более ООПшно) потому, что данные скорее всего будут приходить извне. Например, с поля ввода на экране или из базы.
То есть нужно распечатать именно добавленные ранее сообщения. То есть Forum должен хранить внутри себя список сообщений, а так как нам нужно выводить еще имя автора, храним еще и список авторов.
Добавь внутри форума два мутабельных списка сообщений и пользователей, добавляй в них объекты в методах `newUser()` и `newMessage()`
`newForum.printThread()` не имеет параметров и вызывается один раз, печатая все сообщения хранящиеся в форуме
1) Поля для User'а могут передаваться прямо в метод newUser(...), тогда их можно сделать не var, а val (в целом предпочтительнее использовать val, то есть делать классы иммутабельными, неизменяемые).
2) id должен проставляться внутри newUser(). Так как Forum является фабрикой, можно предоставить ему возможность проставлять id, при этом он будет хранить последний выданный id и увеличивать его на единицу, тем самым гарантировать уникальность значения поля id
Внутри классов Forum и User лучше не использовать readln, так ты делаешь их менее универсальными, явно указав способ получения значений полей через консоль. Давай передавать все что ты читаешь readLn'ом через параметры newUser() и newMessage(). Тогда в будущем можно переиспользовать их, к примеру для бота, в котором bio получаешь через сообщение в телеграмм.
Пускай классы пользователя и сообщения будут без тела, чтобы использовать их исключительно для хранения моделей данных. А вся логика будет заключена в классе форум.
Информацию про патерн строитель можно почитать тут [https://refactoring.guru/ru/design-patterns/builder](https://refactoring.guru/ru/design-patterns/builder)
🧾 Решение¶
class User42(
val id: Int,
val userName: String,
val password: String,
val email: String,
)
class Message(
val id: Int,
val author: User42,
val text: String,
)
class Forum(
private var messageIdCounter: Int = 0,
private var userIdCounter: Int = 0,
private val authors: MutableList<User42> = mutableListOf(),
private val messages: MutableList<Message> = mutableListOf(),
) {
fun newUser(username: String, password: String, email: String): User42 {
val user = User42(
id = userIdCounter,
userName = username,
password = password,
email = email,
)
authors.add(user)
userIdCounter++
return user
}
fun newMessage(authorId: Int, text: String) {
val user = authors.find { it.id == authorId }
?: throw IllegalStateException("Author with id $authorId not found on forum")
val message = Message(id = messageIdCounter, author = user, text = text)
messages.add(message)
messageIdCounter++
}
fun printThread() {
messages.forEach {
println("${it.author.userName}: ${it.text}")
}
}
}
fun main() {
val forum = Forum()
val arthur = forum.newUser("Arthur", "pass1", "arthur.dent@mail.ru")
val marvin = forum.newUser("Marvin", "pass2", "marvin@mail.ru")
forum.newMessage(arthur.id, "Hello, Marv!")
forum.newMessage(marvin.id, "Hi, Arthur!")
forum.newMessage(arthur.id, "It is ok?")
forum.newMessage(marvin.id, "Don't panic")
forum.printThread()
}
// вариант с UUID (тоже норм)
class ForumMember(val userId: UUID, val userName: String)
class ForumMessage(val authorId: UUID, val message: String)
class Forum {
private val members = mutableListOf<ForumMember>()
private val messages = mutableListOf<ForumMessage>()
fun createNewUser(userName: String): ForumMember {
val newUser = ForumMember(UUID.randomUUID(), userName)
members.add(newUser)
return newUser
}
fun createNewMessage(authorId: UUID, message: String): ForumMessage? {
if (members.any { it.userId == authorId }) {
val newMessage = ForumMessage(authorId, message)
messages.add(newMessage)
return newMessage
}
return null
}
fun printMessage() {
for (message in messages) {
for (member in members) {
if (member.userId == message.authorId) {
println("${member.userName}: ${message.message}")
}
}
}
}
}
fun main() {
val forum = Forum()
val user1 = forum.createNewUser("Вася")
val user2 = forum.createNewUser("Петя")
forum.createNewMessage(user1.userId, "Сообщение от Васи, ${user1.userId}")
forum.createNewMessage(user1.userId, "Еще одно сообщение от Васи")
forum.createNewMessage(user2.userId, "Петя пишет, ${user2.userId}")
forum.createNewMessage(user2.userId, "Петя пишет второй раз")
forum.printMessage()
}