Parcourir la source

add chain of responsibility pattern

MrOzOn il y a 4 ans
Parent
commit
8f1eadfca2

+ 22 - 0
src/behavioral_pattern/README.MD

@@ -0,0 +1,22 @@
+# [Цепочка обязанностей (Chain of responsibility)](./chain_of_responsibility/main.kt)
+
+Это поведенческий паттерн проектирования, который позволяет передавать запросы последовательно по цепочке обработчиков. Каждый последующий обработчик решает, может ли он обработать запрос сам и стоит ли передавать запрос дальше по цепи.
+Позволяет избежать привязки отправителя запроса к его получателю, предоставляя возможность обработать запрос нескольким объектам.
+
+## Применимость
+
+- запрос может быть обработан более чем одним объектом, причем настоящий обработчик заранее неизвестен и должен быть найден автоматически
+- запрос должен быть отправлен одному из нескольких объектов, без явного указания, какому именно
+- набор объектов, способных обработать запрос, должен задаваться динамически
+
+## Отношения
+
+Запрос, инициированный клиентом, продвигается по цепочке, пока некоторый объект не возьмет на себя ответственность за его обработку
+
+## Результаты
+
+- ослабление связанности. Паттерн освобождает объект от необходимости знать, кто конкретно обработает его запрос.
+- дополнительная гибкость при распределении обязанностей между объектами. Цепочка обязанностей позволяет повысить гибкость распределения обязанностей между объектами. Добавить или изменить обязанности по обработке запроса можно, включив в цепочку новых участников или изменив ее каким-то другим образом.
+- _получение не гарантировано_. Поскольку у запроса нет явного получателя, то нет и гарантий, что он вообще будет обработан: он может достичь конца цепочки и пропасть.
+
+

+ 24 - 0
src/behavioral_pattern/chain_of_responsibility/AuthServer.kt

@@ -0,0 +1,24 @@
+package behavioral_pattern.chain_of_responsibility
+
+class AuthServer {
+    private val users: MutableMap<String, String> = mutableMapOf()
+    private var middleware: Middleware? = null
+
+    init {
+        println("loading users")
+        users["user1@mydomain.com"]="user1"
+        users["user2@mydomain.com"]="user2"
+        users["user3@mydomain.com"]="user3"
+        users["aDmIn@mydomain.com"]="topsecret"
+    }
+
+    fun initializeMiddleware(middleware: Middleware) {
+        this.middleware = middleware
+    }
+
+    fun loadUsers() = users.toMap()
+
+    fun logIn(email: String, password: String){
+        middleware?.check(email, password)
+    }
+}

+ 62 - 0
src/behavioral_pattern/chain_of_responsibility/ConcreteMiddlewares.kt

@@ -0,0 +1,62 @@
+package behavioral_pattern.chain_of_responsibility
+
+import java.util.*
+
+class ThrottlingMiddleware(private val requestPerMinute: Int) : Middleware() {
+
+    private var currentTime: Long = Date().time
+    private var request = 0
+
+    init {
+        println("ThrottlingMiddleware")
+    }
+
+    override fun check(email: String, password: String): Boolean {
+        if (Date().time > currentTime + 60_000) {
+            request = 0
+            currentTime = Date().time
+        }
+        request++
+        if (request > requestPerMinute) {
+            println("reject - request limit")
+            return false
+        }
+        return checkNext(email, password)
+    }
+}
+
+class UserExistsMiddleware(private val users: Map<String, String>): Middleware() {
+
+    init {
+        println("UserExistsMiddleware")
+    }
+
+    override fun check(email: String, password: String): Boolean {
+        val passwordForUser = users[email]
+        if (passwordForUser==null){
+            println("reject - user \"$email\" not found")
+            return false
+        }
+        if (passwordForUser != password) {
+            println("reject - incorrect password")
+            return false
+        }
+        return checkNext(email, password)
+    }
+}
+
+class RoleCheckMiddleware: Middleware() {
+
+    init {
+        println("RoleCheckMiddleware")
+    }
+
+    override fun check(email: String, password: String): Boolean {
+        if (email.startsWith("aDmIn")) {
+            println("success - welcome admin")
+            return true
+        }
+        return checkNext(email, password)
+    }
+
+}

+ 21 - 0
src/behavioral_pattern/chain_of_responsibility/Middleware.kt

@@ -0,0 +1,21 @@
+package behavioral_pattern.chain_of_responsibility
+
+abstract class Middleware {
+    private var next: Middleware? = null
+
+    fun linkWith(next: Middleware): Middleware {
+        this.next = next
+        return next
+    }
+
+    abstract fun check(email: String, password: String): Boolean
+
+    protected fun checkNext(email: String, password: String): Boolean{
+        return if (next==null){
+            println("for user \"$email\" access allowed")
+            true
+        } else {
+            next!!.check(email, password)
+        }
+    }
+}

+ 16 - 0
src/behavioral_pattern/chain_of_responsibility/main.kt

@@ -0,0 +1,16 @@
+package behavioral_pattern.chain_of_responsibility
+
+fun main(){
+    val authServer = AuthServer()
+    val middleware = ThrottlingMiddleware(5)
+    middleware.linkWith(RoleCheckMiddleware())
+        .linkWith(UserExistsMiddleware(authServer.loadUsers()))
+
+    authServer.initializeMiddleware(middleware)
+    authServer.logIn("aaa@mydomain.com","bbbb")
+    authServer.logIn("user3@mydomain.com","bbbb")
+    authServer.logIn("aDmIn@mydomain.com","bbbb")
+    authServer.logIn("user3@mydomain.com","user3")
+    authServer.logIn("user3@mydomain.com","bbbb")
+    authServer.logIn("user3@mydomain.com","bbbb")
+}