The chain of responsibility pattern is used to process varied requests, each of which may be dealt with by a different handler.
Setup
- Handler: define the interface for handling request, (optional)implements the successor link
- Concrete Handler: handles the request it is responsible for; can access its successor; if the ConcreteHandler can handle this request, then handle it, otherwise it forwards the request to its successor.
- Client: initiates a request to a ConcreteHandler object on the chain.
Example 1
// Step 3: Client code
fun main(args: Array<String>) {
val arcSoldiers = ArcSoldiers()
val swordSoldiers = SwordSoldiers()
val cookSoldiers = CookSoidlers()
fun orderChain(arcSoldiers: ArcSoldiers,
swordSoldiers: SwordSoldiers,
cookSoidlers: CookSoidlers): Soldiers{
arcSoldiers.next = swordSoldiers
swordSoldiers.next = cookSoidlers
return arcSoldiers
}
val soldiers = orderChain(arcSoldiers, swordSoldiers, cookSoldiers)
soldiers.onCall("arrows")
soldiers.onCall("cook")
soldiers.onCall("swing")
soldiers.onCall("cannon")
}
// Step 1: Define the request interface
interface Soldiers{
fun onCall(order: String)
}
// Step 2: ConcreteHandlers to deal with different orders
class ArcSoldiers(var next: Soldiers? = null): Soldiers{
override fun onCall(order: String) {
if (order == "arrows")
println("Aye! Loose the arrows!")
else
next?.onCall(order)?: println("General, we are short-handed.")
}
}
class SwordSoldiers(var next: Soldiers? = null): Soldiers{
override fun onCall(order: String) {
if(order == "swing")
println("Aye! Swing the swords!")
else
next?.onCall(order)?: println("General, we are short-handed.")
}
}
class CookSoidlers(var next: Soldiers? =null): Soldiers{
override fun onCall(order: String) {
if (order == "cook")
println("Aye! Cook the dinners!")
else
next?.onCall(order)?: println("General, we are short-handed.")
}
}
/**
prints
Aye! Loose the arrows!
Aye! Cook the dinners!
Aye! Swing the swords!
General, we are short-handed.
**/
Example 2
// Step 3: Client code
fun main(args: Array<String>) {
val authenticationHeader = AuthenticationHeader("123456")
val contentTypeHeader = ContentTypeHeader("json")
val messageBody = BodyPayload("{\"username\"=\"dbacinski\"}")
// Here in 'fun messageChainWithAuthorization()', client could define the successors.
fun messageChainWithAuthorization(authenticationHeader: AuthenticationHeader,
contentTypeHeader: ContentTypeHeader,
messageBody: BodyPayload): MessageChain {
authenticationHeader.next = contentTypeHeader
contentTypeHeader.next = messageBody
return authenticationHeader
}
val messageChainWithAuthorization = messageChainWithAuthorization(authenticationHeader,
contentTypeHeader,
messageBody)
val messageWithAuthentication = messageChainWithAuthorization.addLines(
"Message with Authentication:\n")
println(messageWithAuthentication)
}
// Step 1: Define the interface for handling request.
interface MessageChain {
fun addLines(inputHeader: String): String
}
// Step 2: ConcreteHandler to handle specific request.
class AuthenticationHeader(val token: String?, var next: MessageChain? = null) : MessageChain {
override fun addLines(inputHeader: String): String {
token ?: throw IllegalStateException("Token should be not null")
return "$inputHeader Authorization: Bearer $token\n".let { next?.addLines(it) ?: it }
}
}
class ContentTypeHeader(val contentType: String, var next: MessageChain? = null) : MessageChain {
override fun addLines(inputHeader: String): String
= "$inputHeader ContentType: $contentType\n".let { next?.addLines(it) ?: it }
}
class BodyPayload(val body: String, var next: MessageChain? = null) : MessageChain {
override fun addLines(inputHeader: String): String
= "$inputHeader $body\n".let { next?.addLines(it) ?: it }
}
/**
prints
Message with Authentication:
Authorization: Bearer 123456
ContentType: json
{"username"="dbacinski"}
**/
NOTE
Safe call operator '?.' & Elvis operator '?:'
// Safe call operator ?.
/**
foo?.bar()
in Kotlin is same as
if(foo == null)
return null;
else
return foo.bar();
in Java
In plain words, if foo is null then returns null, otherwise returns foo.bar()
**/
// Elvis operator ?:
/**
foo?:bar
in Kotlin is same as
if(foo != null)
return foo;
else
return bar;
in Java
In plain words, if foo is NOT null, return itself, otherwise it returns the
value after the elvis operator.
**/
// Combination of safe call operator & elvis operator
/**
For example
a == b is same as:
a?.equals(b)?:(b === null)
in plain words:
if a === null, return (b === null), if (b === null), return true;
if a !== null, return a.equals(b), which is true or false.
**/