Paradigm shift - from behaviours inside object in OOAD to Julia where behaviours emerge from type of function parameters - State Design Pattern - julian way

OOAD Thought Processing

Concept → Owner

  • Behavior → Object
  • Polymorphism → Virtual methods
  • Extension → Subclassing
  • Encapsulation → Methods inside class

Julia Thought Processing

Concept → Owner

  • Behavior → Generic function
  • Polymorphism → Multiple dispatch
  • Extension → Add new methods
  • Encapsulation → Types + modules

OO Design Thinking

  • Identify entities (classes)
  • Attach behavior to them
  • Use inheritance for variation

Julia Design Thinking

  • Identify operations (functions)
  • Define data types
  • Implement methods for combinations of types

Worldview Comparison

OOP worldview

The world is made of interacting objects.

Julia worldview

The world is made of operations applied to data.

The State Pattern in Pure Julia Style

Enjoy the State pattern written in Julia.

Note that this works without the context class of the original State Pattern, which is typically implemented using object-oriented languages like C++, Java, or Python.

# 1. Define the State Hierarchy
abstract type ChickenState end

struct Uncleaned  <: ChickenState end
struct Washed     <: ChickenState end
struct Marinated  <: ChickenState end
struct Cooked     <: ChickenState end

# 2. Define State Transitions (Multiple Dispatch)

# --- Washing ---
function wash(::Uncleaned)
    println("Chicken is getting cleaned → Washed")
    sleep(2)
    return Washed()
end

wash(s::ChickenState) = s  # Default: no change if already washed/cooked

# --- Marinating ---
function marinate(::Washed)
    println("Chicken is being marinated → Marinated")
    sleep(2)
    return Marinated()
end

marinate(s::ChickenState) = s

# --- Cooking ---
function cook(::Marinated)
    println("Chicken is being cooked → Cooked")
    sleep(4)
    return Cooked()
end

cook(s::ChickenState) = s

# --- Serving ---
function serve(::Cooked)
    println("Chicken is being served. Final state.")
    return Cooked()
end

serve(s::ChickenState) = (println("Can't serve yet, chicken is $(typeof(s))"); s)

# 3. Execution Flow
state = Uncleaned()

state = wash(state)
state = marinate(state)
state = cook(state)
state = serve(state)

Enjoy…

And here’s the link of the same application written in Python.
You must feel the difference…

https://som-itsolutions.blogspot.com/2023/03/the-state-pattern-in-python.html

1 Like

I don’t see the difference or the “paradigm shift”. Julia’s wash(s::ChickenState) = s is Python’s:

class ChickenState:
    def wash(s):
        return s

It’s essentially the same thing: the behavior of wash changes depending on the type of the first argument. Julia’s abstract types like ChickenState usually define default versions of the API’s functions, just like Python’s base classes do. So the two systems seem largely the same.

What Python can’t easily do is dispatch on types of multiple arguments, like show(::IO, ::MyCustomType).