Created
August 18, 2022 17:19
-
-
Save xxfast/01608e3fb49bd0686702b88893f06b31 to your computer and use it in GitHub Desktop.
Decorator / Proxy design pattern need not apply?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data class Request(val url: String) | |
data class Response(val code: Int, val body: String) | |
typealias Operation = (request: Request) -> Unit | |
typealias Input = (Request) -> Response? | |
typealias Output = (Request, Response) -> Unit | |
class Process(val output: Output? = null, val input: Input) | |
class Processor { | |
internal val processes: MutableList<Process> = mutableListOf( | |
Process { request: Request -> Response(200, "pong! ${request.url}") }, | |
) | |
fun process(request: Request): Response { | |
val order: List<Process> = processes.reversed() | |
order.forEach { step -> | |
val response: Response? = step.input(request) | |
if (response != null) { | |
processes.forEach { process -> process.output?.invoke(request, response) } | |
return response | |
} | |
} | |
throw IllegalArgumentException("No processor to process $request") | |
} | |
} | |
fun Processor.decorate(operation: Operation) = apply { | |
processes += Process { request: Request -> operation(request); null } | |
} | |
fun Processor.proxy(input: Input, output: Output) = apply { | |
processes += Process( | |
input = { request: Request -> input(request) }, | |
output = { request, response -> output(request, response) } | |
) | |
} | |
fun interface Logger { fun log(request: Request) } | |
fun Processor.log(logger: Logger): Processor = decorate { request -> logger.log(request) } | |
typealias Cache = MutableMap<Request, Response> | |
fun emptyCache(): Cache = mutableMapOf() | |
fun Processor.cache(cache: Cache = emptyCache()): Processor = proxy( | |
input = { request -> | |
val response: Response? = cache[request] | |
response | |
}, | |
output = { request, response -> | |
cache += request to response | |
} | |
) | |
fun main() { | |
val request = Request("https://http.cat/200") | |
val processor = Processor() | |
.log { println("LOG: $it") } | |
.cache() | |
// Don't touch ✋ | |
processor.process(request) | |
processor.process(request) | |
val response: Response = processor.process(request) | |
println(response) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment