Skip to content

Instantly share code, notes, and snippets.

@Mardiniii
Created June 1, 2018 05:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mardiniii/209aa9fa3e5ed451d50f291a2025135a to your computer and use it in GitHub Desktop.
Save Mardiniii/209aa9fa3e5ed451d50f291a2025135a to your computer and use it in GitHub Desktop.
Design Patterns using Ruby
# Adaptee
class Hammer
def swing
'swing'
end
end
# Target
class Tool
def initialize(adapter)
@adapter = adapter
end
def use_tool
@adapter.use_tool
end
end
# Adapter
class HammerAdapter
def initialize(hammer)
@hammer = hammer
end
def use_tool
@hammer.swing
end
end
hammer = Hammer.new
hammer_adapter = HammerAdapter.new(hammer)
tool = Tool.new(hammer_adapter)
puts tool.use_tool
puts tool.use_tool
puts tool.use_tool
class Payment
attr_reader :country, :amount
def initialize(country, amount)
@country = country
@amount = amount
end
end
# North american payments
class PayPalHandler < PaymentHandler
COUNTRIES = ['United States', 'Mexico', 'Canada']
private_constant :COUNTRIES
def accept_payment(payment)
if COUNTRIES.include?(payment.country)
charge(payment)
true
else
false
end
end
private
def charge(payment)
# Logic to process payment with PayPal
puts "Processing payment for #{payment.country} for #{payment.amount} with PayPal"
end
end
# Latin american payments
class StripeHandler < PaymentHandler
COUNTRIES = ['Colombia', 'Brasil', 'Argentina']
private_constant :COUNTRIES
def accept_payment(payment)
if COUNTRIES.include?(payment.country)
charge(payment)
true
else
false
end
end
def charge(payment)
# Logic to process payment with Stripe
puts "Processing payment for #{payment.country} for #{payment.amount} with Stripe"
end
end
class PaymentHandler
attr_accessor :next_receiver
def initialize(next_receiver = nil)
@next_receiver = next_receiver
end
def process_payment(payment)
if accept_payment(payment)
return
elsif @next_receiver
@next_receiver.process_payment(payment)
else
reject_payment(payment)
end
end
def reject_payment(payment)
puts "The payment for #{payment.country} for #{payment.amount} can not be processed with any gateway"
end
def accept_payment(payment)
raise NotImplementedError
end
end
north_american_payment = Payment.new('United States', 450)
latin_american_payment = Payment.new('Colombia', 300)
unvalid_european_payment = Payment.new('Spain', 150)
chain_of_responsibility = StripeHandler.new(PayPalHandler.new())
chain_of_responsibility.process_payment(latin_american_payment)
chain_of_responsibility.process_payment(north_american_payment)
chain_of_responsibility.process_payment(unvalid_european_payment)
class Driver
def pick_up_at(address, date)
puts "Ready for picking up at #{address} on #{date}"
end
end
class Restaurant
def order_for(address, plate)
puts "Ready for cooking #{plate} to #{address}"
end
end
# Services
class DriverService
attr_reader :address, :date, :driver
def initialize(address, date)
@address = address
@date = date
@driver = Driver.new
end
def execute
driver.pick_up_at(address, date)
end
end
class FoodService
attr_reader :address, :plate
def initialize(address, plate)
@address = address
@plate = plate
@restaurant = Restaurant.new
end
def execute
@restaurant.order_for(address, plate)
end
end
class Secretary
def initialize(name)
@name = name
@request_list = []
end
def add_request(request)
@request_list << request
end
def dispatch_requests
@request_list.each do |request|
request.execute
end
end
end
class Boss
def submit_request(secretary, request)
secretary.add_request(request)
end
end
boss = Boss.new
secretary = Secretary.new('Linda')
driver_service = DriverService.new("7901 South Main Street", Time.now)
food_service = FoodService.new("7901 South Main Street", 'Baby Beef')
boss.submit_request(secretary, driver_service)
boss.submit_request(secretary, food_service)
driver_service = DriverService.new("Casa Tia Ilse", Time.now + 1 * 86400)
food_service = FoodService.new("7901 South Main Street", 'Salad and shrimp')
boss.submit_request(secretary, driver_service)
boss.submit_request(secretary, food_service)
driver_service = DriverService.new("Mountain view hospital", Time.now + 2 * 86400)
food_service = FoodService.new("7901 South Main Street", 'Bandeja Paisa')
boss.submit_request(secretary, driver_service)
boss.submit_request(secretary, food_service)
secretary.dispatch_requests
require 'byebug'
class Ticket
attr_accessor :price
def price
99.99
end
end
class TicketWithSpecialAccess
def initialize(ticket)
@ticket = ticket
end
def price
@ticket.price + 49.99
end
end
class TicketWithDiscount
def initialize(ticket)
@ticket = ticket
end
def price
@ticket.price * 0.5
end
end
ticket = Ticket.new
ticket = TicketWithSpecialAccess.new(ticket)
ticket = TicketWithDiscount.new(ticket)
puts ticket.price
class Shape
def draw
raise NotImplementedError
end
end
class Triangle < Shape
def initialize(a, b, c)
@a = a
@b = b
@c = c
end
def draw
"drawing triangle with sides: #{@a} #{@b} #{@c}"
end
end
class Circle < Shape
def initialize(radius)
@radius = radius
end
def draw
"drawing circle with radius: #{@radius}"
end
end
class Square < Shape
def initialize(side)
@side = side
end
def draw
"drawing square with side #{@side}"
end
end
class Rectangule < Shape
def initialize(width, height)
@width = width
@height = height
end
def draw
"drawing rectangule with with #{@width} and height #{@height}"
end
end
class ShapeFactory
TYPES = {
triangle: Triangle,
circle: Circle,
square: Square,
rectangule: Rectangule
}
private_constant :TYPES
def self.for(shape, attributes)
raise NotImplementedError if TYPES[shape].nil?
TYPES[shape].new(*attributes)
end
end
triangle = ShapeFactory.for(:triangle, [5, 6, 7])
puts triangle.draw
circle = ShapeFactory.for(:circle, [5])
puts circle.draw
square = ShapeFactory.for(:square, [7])
puts square.draw
rectangule = ShapeFactory.for(:rectangule, [5, 6])
puts rectangule.draw
# Observable logic
module Observable
def initialize
@observers = []
end
def add_observer(observer)
@observers << observer
end
def delete_observer(observer)
@observers.delete(observer)
end
def notify_observers(date)
@observers.each { |o| o.update(date) }
end
end
module DateFormat
def format(date)
date.strftime("%A - %B %d, %Y")
end
end
# Observable
class League
include Observable
include DateFormat
def initialize(name)
super()
@name = name
end
def set_game_day(args)
date = Time.new(*args)
puts "League: The game will be on: #{format(date)}"
notify_observers(date)
end
end
# Observers
class SoccerTeam
include DateFormat
def initialize(name, league)
@name = name
league.add_observer(self)
end
def update(date)
puts "Team #{@name}: We are ready for the game on #{format(date)}"
end
end
class Referee
include DateFormat
def initialize(name, league)
@name = name
league.add_observer(self)
end
def update(date)
puts "Referee #{@name}: I am ready for the game on #{format(date)}"
end
end
soccer_league = League.new('World Cup Soccer League')
colombia = SoccerTeam.new('Colombia', soccer_league)
japan = SoccerTeam.new('Japan', soccer_league)
referee = Referee.new('Pierluigi Collina', soccer_league)
soccer_league.set_game_day([2018, 06, 19, 17, 30, 0, "+03:00"])
class Node
def accept(visitor)
raise NotImpelementedError.new
end
end
module Visitable
def accept(visitor)
visitor.visit self
end
end
class IntegerNode < Node
include Visitable
attr_reader :value
def initialize(value)
@value = value
end
end
class Ast < Node
def initialize
@nodes = []
@nodes << IntegerNode.new(2)
@nodes << IntegerNode.new(3)
end
def accept(visitor)
@nodes.each do |node|
node.accept visitor
end
end
end
class DoublerVisitor
def visit(subject)
puts subject.value * 2
end
end
class TriplerVisitor
def visit(subject)
puts subject.value * 3
end
end
ast = Ast.new
puts "Doubler:"
ast.accept DoublerVisitor.new
puts "Tripler:"
ast.accept TriplerVisitor.new
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment