← Назад к вопросам
Приведи пример делегирования
1.0 Junior🔥 81 комментариев
#Kotlin основы#Архитектура и паттерны
Комментарии (1)
🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Пример делегирования (Delegation Pattern) в Android/Kotlin
Делегирование — это шаблон проектирования, при котором один объект передаёт часть своей ответственности другому объекту. В отличие от наследования, делегирование использует композицию, что делает код более гибким и соответствует принципу "предпочитайте композицию наследованию".
Ключевые преимущества делегирования:
- Избегание проблем хрупкого базового класса (fragile base class problem)
- Возможность динамической смены поведения во время выполнения
- Более чистая архитектура с разделением ответственности
- Поддержка принципа единственной ответственности (Single Responsibility Principle)
Практический пример делегирования в Android
Рассмотрим реальный сценарий: нам нужно создать делегирование для обработки кликов в RecyclerView, чтобы отделить логику обработки кликов от адаптера.
1. Создаём интерфейс делегата
// Интерфейс, определяющий контракт для обработки кликов
interface ItemClickDelegate<T> {
fun onItemClick(item: T, position: Int)
fun onItemLongClick(item: T, position: Int): Boolean
}
2. Реализуем конкретный делегат
// Конкретная реализация делегата для обработки кликов по пользователям
class UserClickDelegate(
private val context: Context,
private val onUserSelected: (User) -> Unit
) : ItemClickDelegate<User> {
override fun onItemClick(item: User, position: Int) {
// Делегируем обработку клика
Toast.makeText(context, "Clicked: ${item.name}", Toast.LENGTH_SHORT).show()
onUserSelected(item)
// Можно добавить аналитику, навигацию и другую логику
AnalyticsTracker.trackUserClick(item.id)
}
override fun onItemLongClick(item: User, position: Int): Boolean {
// Делегируем обработку долгого клика
showUserOptionsDialog(item)
return true
}
private fun showUserOptionsDialog(user: User) {
// Логика показа диалога
}
}
###系统3. Используем делегирование в адаптере RecyclerView
class UserAdapter(
private val users: List<User>,
// Внедряем делегат через композицию (не наследование!)
private val clickDelegate: ItemClickDelegate<User>
) : RecyclerView.Adapter<UserAdapter.UserViewHolder>() {
class UserViewHolder(
itemView: View,
private val delegate: ItemClickDelegate<User>
) : RecyclerView.ViewHolder(itemView) {
private val nameTextView: TextView = itemView.findViewById(R.id.tv_name)
private val emailTextView: TextView = itemView.findViewById(R.id.tv_email)
fun bind(user: User) {
nameTextView.text = user.name
emailTextView.text = user.email
// Делегируем обработку кликов
itemView.setOnClickListener {
delegate.onItemClick(user, adapterPosition)
}
itemView.setOnLongClickListener {
delegate.onItemLongClick(user, adapterPosition)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_user, parent, false)
return UserViewHolder(view, clickDelegate)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
holder.bind(users[position])
}
override fun getItemCount() = users.size
}
4. Пример использования в Activity/Fragment
class UserListFragment : Fragment() {
private lateinit var adapter: UserAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val recyclerView: RecyclerView = view.findViewById(R.id.recycler_view)
// Создаём делегат с конкретной логикой
val clickDelegate = UserClickDelegate(requireContext()) { user ->
// Действие при выборе пользователя
navigateToUserDetails(user)
}
// Передаём делегат в адаптер
adapter = UserAdapter(getUsers(), clickDelegate)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(requireContext())
}
private fun navigateToUserDetails(user: User) {
// Навигация к деталям пользователя
}
private fun getUsers(): List<User> {
return listOf(
User(1, "Анна", "anna@example.com"),
User(2, "Иван", "ivan@example.com"),
User(3, "Мария", "maria@example.com")
)
}
}
Вариации делегирования в Kotlin
Использование встроенной поддержки делегирования в Kotlin
// Пример с property delegation
class UserRepository {
// Делегируем кэширование свойству
val cachedUsers: List<User> by lazy {
loadUsersFromDatabase()
}
// Делегируем логирование observable property
var lastUpdated: Long by Delegates.observable(System.currentTimeMillis()) {
property, oldValue, newValue ->
Log.d("UserRepository", "Last updated changed from $oldValue to $newValue")
}
private fun loadUsersFromDatabase(): List<User> {
// Загрузка из БД
return emptyList()
}
}
Делегирование с помощью by в Kotlin
// Интерфейс для загрузки данных
interface DataLoader {
fun loadData(): String
}
// Реальная реализация
class NetworkDataLoader : DataLoader {
override fun loadData(): String {
return "Data from network"
}
}
// Класс, который делегирует вызовы
class CachedDataLoader(
private val realLoader: DataLoader
) : DataLoader by realLoader {
// Мы можем переопределить только нужные методы
private var cache: String? = null
override fun loadData(): String {
if (cache == null) {
cache = realLoader.loadData()
}
return cache!!
}
// И добавить новые методы
fun clearCache() {
cache = null
}
}
Вывод
Делегирование в Android разработке позволяет:
- Разделять ответственность между компонентами
- Упрощать тестирование — делегаты можно тестировать изолированно
- Повышать переиспользуемость кода
- Соблюдать принципы SOLID, особенно принцип открытости/закрытости
- Уменьшать связность между компонентами
В примере выше мы видим, как делегирование обработки кликов позволяет:
- Отделить бизнес-логику от UI-логики
- Легко менять поведение при кликах без изменения адаптера
- Переиспользовать логику обработки кликов в разных частях приложения
- Упрощать поддержку и расширение функциональности