Skip to content

Instantly share code, notes, and snippets.

@shubhamwagh
Last active December 1, 2023 22:16
Show Gist options
  • Save shubhamwagh/02e19bdd91e3cdb7200c55d2ea3277d3 to your computer and use it in GitHub Desktop.
Save shubhamwagh/02e19bdd91e3cdb7200c55d2ea3277d3 to your computer and use it in GitHub Desktop.
State Design Pattern Tutorial
from dataclasses import dataclass
from typing import Protocol
# State Interface
class DocumentState(Protocol):
def edit(self):
...
def review(self):
...
def finalise(self):
...
# State Context
class DocumentContext(Protocol):
content: list[str]
def set_state(self, state: DocumentState):
...
def edit(self):
...
def review(self):
...
def finalise(self):
...
def show_content(self):
...
# Concrete State
@dataclass
class Draft:
document: DocumentContext
def edit(self):
print("Editing the document....")
self.document.content.append("Edited content.")
def review(self):
print("Document under review")
self.document.set_state(Review(self.document))
def finalise(self):
print("You need to review the document before finalising.")
# Concrete State
@dataclass
class Review:
document: DocumentContext
def edit(self):
print("The document is under review, cannot edit now.")
def review(self):
print("The document is already reviewed.")
def finalise(self):
print("Finalising the document....")
self.document.set_state(Publish(self.document))
# Concrete State
@dataclass
class Publish:
document: DocumentContext
def edit(self):
print("The document is finalised. Editing is not allowed.")
def review(self):
print("The document is finalised. Review is not possible.")
def finalise(self):
print("The document is already finalised.")
# Object
class Document:
def __init__(self):
self.state: DocumentState = Draft(self)
self.content: list[str] = []
def set_state(self, state):
self.state = state
def edit(self):
self.state.edit()
def review(self):
self.state.review()
def finalise(self):
self.state.finalise()
def show_content(self):
print("Document content:", " ".join(self.content))
def main():
document = Document()
document.edit()
document.review()
document.edit()
document.finalise()
document.review()
document.edit()
document.show_content()
if __name__ == "__main__":
main()
from typing import Protocol
# State Interface
class LightState(Protocol):
def switch(self, bulb) -> None:
...
# Object
class Bulb:
def __init__(self):
self.state = OnState()
def switch(self) -> None:
self.state.switch(self)
# Concrete State
class OnState:
def switch(self, bulb) -> None:
bulb.state = OffState()
print("Light is Off.")
# Concrete State
class OffState:
def switch(self, bulb: Bulb) -> None:
bulb.state = OnState()
print("Light is on.")
def main() -> None:
b = Bulb()
b.switch()
b.switch()
if __name__ == '__main__':
main()
  • State Design Pattern allows an object to change its behavior when its internal state changes.
  • It is a behavioral type design pattern.
  • It has State Interface which represents all behaviors (methods) the context will exhibit.
  • The Concrete States in the state design pattern are the implementations of the State Interface that define behaviors specific to each state.
  • It has Context Class that holds a reference to the current state and expose methods to clients.
  • Useful to manage states in the applications and swtich between them.
  • Easy to maintian since each state is a different class and state-specific behavior is encapsulated in its respective class.
  • New states can be easily added by writing an extra class for the new state.
  • E.g. States in a document, states in a game, or different modes in a GUI.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment