** Table of Contents **
I think that you often have a property that manages the state like XXXStatus
, and implement it likeswitch (XXXStatus) {// perform various processing by case}
.
I think that the purpose of this pattern is to make each state an object so that the switch statement will continue for a long time and it will be difficult for the reader to read as the number of states increases. I will.
I think it's similar to the Command pattern (https://qiita.com/takumi0620/items/f7f755a4fe0d1dbfd153).
Causes an object to change its behavior when the internal state of the object changes. In the class, this is achieved by introducing an object that represents the state without describing the change in behavior.
・ Context Class with various states -State state abstract class -ConcreteState state concrete class
We will implement a vending machine. There are the following two states and two operations as the state of the vending machine to be implemented, and the price of the product is uniformly 100 yen. Status ・ The amount less than the price of the item has been deposited. ・ The amount of money that exceeds the price of the product has been deposited.
operation ・ Make a deposit. ・ Press the product button.
State.kt
package state
interface State {
fun coin(v: VendingMachine)
fun push(v: VendingMachine)
}
A class that represents the state in which an amount less than the price of the item has been deposited
LackState.kt
package state
class LackState: State {
override fun coin(v: VendingMachine) {
v.insertMoney(50)
}
override fun push(v: VendingMachine) {
v.errorMessage()
}
}
Classes where the amount of money above the price of the item is deposited
SufficientState.kt
package state
class SufficientState: State {
override fun coin(v: VendingMachine) {
v.warningMessage()
}
override fun push(v: VendingMachine) {
v.buy()
}
}
Abstract class
Context.kt
package state
interface Context {
fun coin()
fun push()
}
Vending machine concrete class
VendingMachine.kt
package state
class VendingMachine: Context {
companion object {
private val lack = LackState()
private val sufficient = SufficientState()
}
private var state: State = lack
private var money = 0
override fun coin() {
state.coin(this)
}
override fun push() {
state.push(this)
}
fun warningMessage() {
println("No further deposit is required.")
}
fun errorMessage() {
println("The required amount has not been entered.")
}
fun insertMoney(m: Int) {
println("I put in the money.")
money += m
if (money >= 100) {
state = sufficient
}
}
fun buy() {
println("Please take out the drink from the outlet.")
state = lack
}
}
Client.kt
package state
class Client {
init {
val v: Context = VendingMachine()
v.coin()
v.push()
v.coin()
v.coin()
v.push()
}
}
[out-put]
I put in the money.
The required amount has not been entered.
I put in the money.
No further deposit is required.
Please take out the drink from the outlet.
I think it would be better to implement the Factory
class, which instantiates the VendingMachine
class of type Context
.
Recommended Posts