Last active
February 4, 2016 21:50
-
-
Save IanWhitney/99605705aa25f154333d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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