Skip to content

Instantly share code, notes, and snippets.

@dmitry-osin
Last active January 25, 2025 11:14
Show Gist options
  • Save dmitry-osin/aa3ecda4ff5a71ffc7462cb886d70c66 to your computer and use it in GitHub Desktop.
Save dmitry-osin/aa3ecda4ff5a71ffc7462cb886d70c66 to your computer and use it in GitHub Desktop.

Шаблоны проектирования


Оглавление


Порождающие шаблоны

Singleton

Описание
Гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к нему.

Реализация

object Singleton {
    fun log(message: String) = println(message)
}

// Использование:
Singleton.log("Hello, Singleton!")

Factory Method

Описание
Делегирует создание объектов подклассам, позволяя изменять тип создаваемых объектов.

Реализация

interface Animal {
    fun speak()
}

class Dog : Animal {
    override fun speak() = println("Гав!")
}

class AnimalFactory {
    fun createAnimal(): Animal = Dog()
}

// Использование:
val factory = AnimalFactory()
val animal = factory.createAnimal()

Abstract Factory

Описание
Создаёт семейства связанных объектов без указания их конкретных классов.

Реализация

interface Button {
    fun render()
}

class WindowsButton : Button {
    override fun render() = println("Отрисована кнопка Windows")
}

interface GUIFactory {
    fun createButton(): Button
}

class WindowsFactory : GUIFactory {
    override fun createButton() = WindowsButton()
}

// Использование:
val factory: GUIFactory = WindowsFactory()
val button = factory.createButton()

Builder

Описание
Поэтапно конструирует сложные объекты, разделяя процесс создания от его представления.

Реализация

class Pizza(
    val dough: String,
    val toppings: List<String>
) {
    class Builder(private val dough: String) {
        private val toppings = mutableListOf<String>()
        fun addTopping(topping: String) = apply { toppings.add(topping) }
        fun build() = Pizza(dough, toppings)
    }
}

// Использование:
val pizza = Pizza.Builder("тонкое тесто")
    .addTopping("сыр")
    .build()

Prototype

Описание
Копирует существующие объекты, избегая зависимости от их классов.

Реализация

data class Robot(val id: String) : Cloneable {
    public override fun clone() = Robot(id)
}

// Использование:
val original = Robot("R2-D2")
val cloned = original.clone()

Структурные шаблоны

Adapter

Описание
Адаптирует интерфейс класса к другому интерфейсу, который ожидают клиенты.

Реализация

class LegacyPrinter {
    fun printLegacy() = println("Печать в старом формате")
}

interface ModernPrinter {
    fun print()
}

class PrinterAdapter(private val legacyPrinter: LegacyPrinter) : ModernPrinter {
    override fun print() = legacyPrinter.printLegacy()
}

// Использование:
val adapter = PrinterAdapter(LegacyPrinter())
adapter.print()

Decorator

Описание
Динамически добавляет объекту новые обязанности, оборачивая его в обёртки.

Реализация

interface Coffee {
    fun cost(): Double
}

class Espresso : Coffee {
    override fun cost() = 2.0
}

class MilkDecorator(private val coffee: Coffee) : Coffee {
    override fun cost() = coffee.cost() + 0.5
}

// Использование:
val coffee: Coffee = MilkDecorator(Espresso())
println(coffee.cost()) // 2.5

Facade

Описание
Упрощает взаимодействие со сложной системой, предоставляя упрощённый интерфейс.

Реализация

class CPU {
    fun start() = println("CPU запущен")
}

class ComputerFacade {
    private val cpu = CPU()
    fun start() = cpu.start()
}

// Использование:
ComputerFacade().start()

Composite

Описание
Объединяет объекты в древовидные структуры для работы с ними как с единым целым.

Реализация

interface Component {
    fun operation()
}

class Leaf : Component {
    override fun operation() = println("Лист выполняет операцию")
}

class Composite : Component {
    private val children = mutableListOf<Component>()
    fun add(component: Component) = children.add(component)
    override fun operation() = children.forEach { it.operation() }
}

// Использование:
val composite = Composite()
composite.add(Leaf())
composite.operation()

Proxy

Описание
Контролирует доступ к объекту, добавляя дополнительную логику (например, ленивую загрузку).

Реализация

interface Image {
    fun display()
}

class RealImage(private val path: String) : Image {
    override fun display() = println("Изображение $path отображено")
}

class ProxyImage(private val path: String) : Image {
    private var realImage: RealImage? = null
    override fun display() {
        if (realImage == null) realImage = RealImage(path)
        realImage!!.display()
    }
}

// Использование:
val image: Image = ProxyImage("photo.jpg")
image.display()

Поведенческие шаблоны

Observer

Описание
Уведомляет зависимые объекты об изменении состояния наблюдаемого объекта.

Реализация

interface Observer {
    fun update(event: String)
}

class User : Observer {
    override fun update(event: String) = println("Событие: $event")
}

class EventManager {
    private val observers = mutableListOf<Observer>()
    fun subscribe(observer: Observer) = observers.add(observer)
    fun notify(event: String) = observers.forEach { it.update(event) }
}

// Использование:
val manager = EventManager()
manager.subscribe(User())
manager.notify("Новое обновление!")

Strategy

Описание
Инкапсулирует алгоритмы в отдельные классы, делая их взаимозаменяемыми.

Реализация

interface PaymentStrategy {
    fun pay(amount: Double)
}

class CreditCardPayment : PaymentStrategy {
    override fun pay(amount: Double) = println("Оплата картой: $amount")
}

class PaymentContext(private var strategy: PaymentStrategy) {
    fun executePayment(amount: Double) = strategy.pay(amount)
}

// Использование:
val context = PaymentContext(CreditCardPayment())
context.executePayment(100.0)

Command

Описание
Инкапсулирует запросы как объекты, позволяя параметризовать клиенты запросами.

Реализация

interface Command {
    fun execute()
}

class LightOnCommand(private val light: Light) : Command {
    override fun execute() = light.turnOn()
}

class Light {
    fun turnOn() = println("Свет включён")
}

// Использование:
val command = LightOnCommand(Light())
command.execute()

Chain of Responsibility

Описание
Передаёт запрос по цепочке обработчиков, пока один из них не обработает его.

Реализация

abstract class Handler {
    var next: Handler? = null
    abstract fun handle(request: String)
}

class AuthHandler : Handler() {
    override fun handle(request: String) {
        if (request == "auth") println("Обработана авторизация") 
        else next?.handle(request)
    }
}

// Использование:
val handler = AuthHandler()
handler.handle("auth")

Iterator

Описание
Последовательно обходит элементы коллекции без раскрытия её внутренней структуры.

Реализация

class BookCollection(private val books: List<String>) {
    fun iterator() = object : Iterator<String> {
        private var index = 0
        override fun hasNext() = index < books.size
        override fun next() = books[index++]
    }
}

// Использование:
val collection = BookCollection(listOf("Книга 1", "Книга 2"))
val iterator = collection.iterator()
while (iterator.hasNext()) println(iterator.next())

Каждая реализация на Kotlin демонстрирует основную идею шаблона. Для упрощения опущены детали вроде потокобезопасности и обработки ошибок, но в реальных проектах их необходимо учитывать.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment