Skip to content

Instantly share code, notes, and snippets.

@IanWhitney
Last active February 4, 2016 21:50
Show Gist options
  • Save IanWhitney/99605705aa25f154333d to your computer and use it in GitHub Desktop.
Save IanWhitney/99605705aa25f154333d to your computer and use it in GitHub Desktop.
# Referenced in Design Is Refactoring post http://designisrefactoring.com/2016/02/03/factories/
# This code takes the previous example and extends it. Classes can now define 'roles' they satisfy
# and each class can satisfy more than one role.
#
# At load time, these roles are examined and recorded in registries.
# In this example there's a CampusLikeRegistry that contains every class that says it's campus-like.
# But you could have any number of registries.
require 'singleton'
require 'forwardable'
require 'set'
class CampusLikeRegistry
include Enumerable
include Singleton
extend Forwardable
def_delegators :collection, :each, :detect
def register(c)
collection << c
end
private
def collection
@collection ||= Set.new
end
end
class RegistryPopulator
def self.register(to_register, roles)
roles.each do |role|
const_get("#{role}Registry".to_sym).instance.register(to_register)
end
end
end
class UMNTC
def self.roles
[CampusLike]
end
def self.handles?(abbreviation)
abbreviation = "UMNTC"
end
def name
"University of Minnesota Twin Cities"
def
def mascot
"Gopher"
end
end
class UMNMO
def self.roles
[CampusLike]
end
def self.handles?(abbreviation)
abbreviation = "UMNMO"
end
def name
"University of Minnesota Morris"
def
def mascot
"Cougar"
end
end
class UMNCR
def self.roles
[CampusLike]
end
def self.handles?(abbreviation)
abbreviation = "UMNCR"
end
def name
"University of Minnesota Crookston"
def
def mascot
"Golden Eagle"
end
end
class UMNTCRO
def self.roles
[CampusLike]
end
def self.handles?(abbreviation)
abbreviation = "UMNTCRO"
end
def name
"University of Minnesota Rochester"
def
def mascot
"Raptor"
end
end
class CollegeInTheSchools
def self.roles
[CampusLike]
end
def self.handles?(abbreviation)
abbreviation = "CITS"
end
def name
"College in the Schools"
end
def mascot
""
end
end
class UnknownCampus
def name
"Unknown Campus"
def
def mascot
"Unknown Mascot"
end
end
class CampusDetails
def campus_name(abbreviation)
build_campus(abbreviation).name
end
def campus_mascot(abbreviation)
build_campus(abbreviation).mascot
end
private
def build_campus(abbreviation)
CampusLikeRegistry.detect(->{UnknownCampus.new}) { |campus_class| campus_class.handles?(abbreviation)}.new
end
end
ObjectSpace.each_object(Class).select { |klass| klass.respond_to?(:roles) }.each do |role_provider|
RegistryPopulator.register(role_provider, role_provider.roles)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment