Procházet zdrojové kódy

add adapter pattern

MrOzOn před 4 roky
rodič
revize
1a34e915b5

+ 37 - 0
src/structural_patterns/README.MD

@@ -0,0 +1,37 @@
+# [Адаптер (Adapter)](./adapter/main.kt)
+
+Это структурный паттерн проектирования, который позволяет объектам с несовместимыми интерфейсами работать вместе. Преобразует интерфейс одного класса в другой интерфейс, на который рассчитаны клиенты.
+
+Адаптеры могут не только переводить данные из одного формата в другой, но и помогать объектам с разными интерфейсами работать сообща. Иногда возможно создать даже _двухсторонний_ адаптер, который работал бы в обе стороны.
+
+**Адаптер объектов**
+Эта реализация использует агрегацию: объект адаптера «оборачивает», то есть содержит ссылку на служебный объект. Такой подход работает во всех языках программирования.
+
+**Адаптер классов**
+Эта реализация базируется на наследовании: адаптер наследует оба интерфейса одновременно. Такой подход возможен только в языках, поддерживающих множественное наследование, например, C++.
+
+## Другое название
+Обертка (Wrapper)
+
+## Применимость
+
+- вы хотите использовать существующий класс, но его интерфейс не соответствует вашим потребностям
+- требуется создать повторно используемый класс, который должен взаимодействовать с заранее неизвестными или не связанными с ним классами, имеющими несовместимые интерфейсы
+- (**_только для адаптера объектов!_**) нужно использовать несколько существующих подклассов, но непрактично адаптировать их интерфейсы путем порождения новых подклассов от каждого. В этом случае адаптер объектов может приспосабливать интерфейс их общего родительского класса
+
+## Отношения
+
+Клиенты вызывают операции экземпляра адаптера Adapter. В свою очередь адаптер вызывает операции адаптируемого объекта или класса Adaptee, который и выполняет запрос.
+
+## Результаты
+
+Адаптеры объектов и классов обладают разными достоинствами и недостатками.
+
+**Адаптер объектов**
+- позволяет одному адаптеру (Adapter) работать со многим адаптируемыми объектами (Adaptee), то есть с самим Adaptee и его подклассами (если таковые имеются). Адаптер может добавить новую функциональность сразу всем адаптируемым объектам
+- затрудняет замещение операций класса Adaptee. Для этого потребуется породить от Adaptee подкласс и заставить Adapter ссылаться на этот подкласс, а не на сам Adaptee
+
+**Адаптер классов**
+- адаптирует адаптируемый класс (Adaptee) к целе (Target), перепоручая действия конкретному классу Adaptee. Поэтому данный паттерн не будет работать, если мы захотим одновременно адаптировать класс и его подклассы
+- позволяет адаптеру (Adapter) заместить некоторые операции адаптируемого класса Adaptee, так как Adapter есть не что иное, как подкласс Adaptee
+- вводит только один новый объект. Чтобы добраться до адаптируемого класса, не нужно никакого дополнительного обращения по указателю

+ 40 - 0
src/structural_patterns/adapter/main.kt

@@ -0,0 +1,40 @@
+package structural_patterns.adapter
+
+import kotlin.math.roundToInt
+import kotlin.math.sqrt
+
+class RoundHole(private val radius:Int){
+    fun fits(peg: RoundPeg) = radius >= peg.radius
+}
+
+open class RoundPeg(val radius:Int)
+
+class SquarePeg(val width:Int)
+
+// This is object adapter, it's contains refer to "our" instance object
+class SquarePegAdapter(peg: SquarePeg): RoundPeg((peg.width * sqrt(2.0) / 2).roundToInt())
+
+fun main(){
+    val hole = RoundHole(5)
+    val roundPeg = RoundPeg(5)
+    println("roundPeg fits in hole = ${hole.fits(roundPeg)}")
+
+    val smallSquarePeg = SquarePeg(5)
+    val largeSquarePeg = SquarePeg(10)
+    /*
+        !!!Compile-time error
+        Type mismatch.
+            Required:
+            RoundPeg
+            Found:
+            SquarePeg
+     */
+//    print("roundPeg fits in hole = ${hole.fits(smallSquarePeg)}")
+//    print("roundPeg fits in hole = ${hole.fits(smallSquarePeg)}")
+
+    // Use adapter for "alien" class SquarePeg
+    val smallSquarePegAdapter = SquarePegAdapter(smallSquarePeg)
+    val largeSquarePegAdapter = SquarePegAdapter(largeSquarePeg)
+    println("smallSquarePeg fits in hole = ${hole.fits(smallSquarePegAdapter)}")
+    println("largeSquarePeg fits in hole = ${hole.fits(largeSquarePegAdapter)}")
+}