I. Visitor Pattern
The Visitor pattern allows you to define new operations on the elements of an object structure without changing the classes of the elements themselves. This pattern is useful when you have a complex object structure with multiple types of elements and want to perform different operations on them without modifying the classes of the elements.
In Ruby, the Visitor pattern can be implemented using a visitor class that defines the operations to be performed on the elements of the object structure. Here’s an example of the Visitor pattern in Ruby:
class Element
def accept(visitor)
raise NotImplementedError, "#{self.class} does not implement accept(visitor)"
end
end
class ConcreteElementA < Element
def accept(visitor)
visitor.visit_concrete_element_a(self)
end
end
class ConcreteElementB < Element
def accept(visitor)
visitor.visit_concrete_element_b(self)
end
end
class Visitor
def visit_concrete_element_a(element)
raise NotImplementedError, "#{self.class} does not implement visit_concrete_element_a(element)"
end
def visit_concrete_element_b(element)
raise NotImplementedError, "#{self.class} does not implement visit_concrete_element_b(element)"
end
end
class ConcreteVisitor < Visitor
def visit_concrete_element_a(element)
puts "Visited ConcreteElementA"
end
def visit_concrete_element_b(element)
puts "Visited ConcreteElementB"
end
end
# Usage
elements = [ConcreteElementA.new, ConcreteElementB.new]
visitor = ConcreteVisitor.new
elements.each { |element| element.accept(visitor) }
II. Memento Pattern
The Memento pattern allows you to capture and externalize an object’s internal state so that the object can be restored to that state later. This pattern is useful when you want to save and restore the state of an object without exposing its internal structure.
In Ruby, the Memento pattern can be implemented using a memento class that stores
class Memento
attr_reader :state
def initialize(state)
@state = state
end
end
class Originator
attr_accessor :state
def create_memento
Memento.new(state)
end
def restore_memento(memento)
@state = memento.state
end
end
class Caretaker
attr_accessor :memento
def add_memento(memento)
@memento = memento
end
end
# Usage
originator = Originator.new
caretaker = Caretaker.new
originator.state = "State1"
caretaker.add_memento(originator.create_memento)
originator.state = "State2"
caretaker.add_memento(originator.create_memento)
originator.state = "State3"
caretaker.add_memento(originator.create_memento)
originator.restore_memento(caretaker.memento)
puts originator.state
III. Mediator Pattern
The Mediator pattern defines an object that encapsulates how a set of objects interact with each other. This pattern is useful when you have a complex system with multiple objects that need to communicate with each other, and you want to decouple the objects from each other to make the system more maintainable and flexible.
In Ruby, the Mediator pattern can be implemented using a mediator class that defines the communication between the objects. Here’s an example of the Mediator pattern in Ruby:
class Mediator
def initialize
@colleagues = []
end
def add_colleague(colleague)
@colleagues << colleague
end
def send(message, colleague)
@colleagues.each do |c|
c.receive(message) unless c == colleague
end
end
end
class Colleague
attr_reader :mediator
def initialize(mediator)
@mediator = mediator
@mediator.add_colleague(self)
end
def send(message)
@mediator.send(message, self)
end
def receive(message)
puts "Received message: #{message}"
end
end
# Usage
mediator = Mediator.new
colleague1 = Colleague.new(mediator)
colleague2 = Colleague.new(mediator)
colleague1.send("Hello from colleague1")
colleague2.send("Hello from colleague2")
IV. Flyweight Pattern
The Flyweight pattern is a structural pattern that allows you to share objects to reduce memory usage and improve performance. This pattern is useful when you have a large number of similar objects that can be shared to save memory and reduce the cost of creating new objects.
In Ruby, the Flyweight pattern can be implemented using a factory class that creates and manages flyweight objects. Here’s an example of the Flyweight pattern in Ruby:
class FlyweightFactory
def initialize
@flyweights = {}
end
def get_flyweight(key)
@flyweights[key] ||= ConcreteFlyweight.new
end
end
class Flyweight
def operation
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
end
class ConcreteFlyweight < Flyweight
def operation
puts "ConcreteFlyweight operation"
end
end
# Usage
factory = FlyweightFactory.new
flyweight1 = factory.get_flyweight("key1")
flyweight2 = factory.get_flyweight("key2")
flyweight1.operation
flyweight2.operation
V. Builder Pattern
The Builder pattern is a creational pattern that separates the construction of a complex object from its representation. This pattern is useful when you want to create an object step by step and have different representations of the object without exposing its internal structure.
In Ruby, the Builder pattern can be implemented using a builder class that constructs the object step by step. Here’s an example of the Builder pattern in Ruby:
class Product
attr_accessor :part1, :part2, :part3
def initialize
@part1 = nil
@part2 = nil
@part3 = nil
end
end
class Builder
def build_part1
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
def build_part2
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
def build_part3
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
end
class ConcreteBuilder < Builder
attr_reader :product
def initialize
@product = Product.new
end
def build_part1
@product.part1 = "Part1"
end
def build_part2
@product.part2 = "Part2"
end
def build_part3
@product.part3 = "Part3"
end
end
class Director
attr_reader :builder
def initialize(builder)
@builder = builder
end
def construct
@builder.build_part1
@builder.build_part2
@builder.build_part3
end
end
# Usage
builder = ConcreteBuilder.new
director = Director.new(builder)
director.construct
product = builder.product
puts product.part1
puts product.part2
puts product.part3
Public comments are closed, but I love hearing from readers. Feel free to contact me with your thoughts.