Created
August 2, 2012 19:44
-
-
Save kevingriffin/3240036 to your computer and use it in GitHub Desktop.
Dependency Injection
This file contains 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
# We have a FunnySentences class. Objects of this class generate five **wacky** phrases with random upper and lower case. | |
# Because the logic of returning the sentences in some modified form is seperate | |
# from the process of generating the sentences, we use a different object to do the generation (single responsiblity princible). | |
# Instead of just using this generation object directly, we assign it to a variable when we create a new FunnySentences object. | |
# Interally, the FunnySentencs object calls methods on this object we pass in, asking it to generate sentences for us. | |
# As long as the generator we pass in returns strings when we call generate on it, | |
# the logic in our FunnySentences class will work no matter what we use for the generator. | |
class FunnySentences | |
# We use an attr_accessor so we can set up an object of a different class to take over the sentence generation | |
attr_accessor :sentence_generator | |
# When we initialize a FunnySentences object, we can pass in a custom generator. By default, it uses the lame one. | |
def initialize(sentence_generator = LameSentenceGenerator.new) | |
self.sentence_generator = sentence_generator | |
end | |
# The rest of our code doesn't need to know about the generator, so we can focus on its logic | |
def wacky_time! | |
get_sentences.map do |sentence| | |
"WHOA! #{sentence}" | |
end | |
end | |
def random_case(sentence) | |
sentence.each_char.map {|c| [c, c.upcase].sample }.join | |
end | |
# We don't have to change any of this logic to use a different generator, provided they both have the same method (generate) | |
def get_sentences | |
sentences = sentence_generator.generate(5) | |
sentences.map do |sentence| | |
random_case(sentence) | |
end | |
end | |
end | |
class LameSentenceGenerator | |
def generate(number) | |
number.times.map { "This one is lame and only makes one sentence" } | |
end | |
end | |
class BetterSentenceGenerator | |
def generate(number) | |
number.times.map do | |
["Two sentences this time!", "Double your pleasure."].sample | |
end | |
end | |
end | |
a = FunnySentences.new | |
a.wacky_time! # => ["WHOA! THIs oNE Is LamE aNd oNlY MaKEs ONe SEntEncE", "WHOA! ThIs OnE is LAme and ONLY MaKes one seNTEnCe", "WHOA! THiS one Is LaME AND onLY MaKEs oNE sEnTeNcE", "WHOA! This One iS Lame anD ONlY makeS oNE SENtence", "WHOA! ThIS onE Is lAmE anD ONly MAkES oNe SeNteNCe"] | |
b = FunnySentences.new(BetterSentenceGenerator.new) | |
b.wacky_time! # => ["WHOA! TWo senTENcEs this time!", "WHOA! Two seNTEnces this time!", "WHOA! DOuBLe Your plEASURE.", "WHOA! DoublE YouR PLeasUrE.", "WHOA! TWO sentENceS ThiS tiMe!"] | |
# We can take this a step further and abstract out the casing of the sentences (since that really isn't the job of our wacky class). | |
class FunnySentencesV2 | |
# This time we can set both a generator and a caser (a word Josh would use in Boggle no doubt) | |
attr_accessor :sentence_generator, :caser | |
# When we initialize a FunnySentences object, we can pass in a custom generator. By default, it uses the lame one. | |
def initialize(sentence_generator = LameSentenceGenerator.new, caser = RandomCaser.new) | |
self.sentence_generator = sentence_generator | |
self.caser = caser | |
end | |
def wacky_time! | |
get_sentences.map do |sentence| | |
"WHOA! #{sentence}" | |
end | |
end | |
def get_sentences | |
sentences = sentence_generator.generate(5) | |
sentences.map do |sentence| | |
# Now we use our caser object instead of the class's own random method | |
caser.case sentence | |
end | |
end | |
end | |
class RandomCaser | |
def case(sentence) | |
sentence.each_char.map {|c| [c, c.upcase].sample }.join | |
end | |
end | |
class UpCaser | |
def case(sentence) | |
sentence.upcase | |
end | |
end | |
class DownCaser | |
def case(sentence) | |
sentence.downcase | |
end | |
end | |
c = FunnySentencesV2.new | |
c.wacky_time! # => ["WHOA! ThIs One iS lAmE anD ONLY mAkes One SENTENCE", "WHOA! ThiS oNe iS LaMe AnD ONlY makes OnE SenTencE", "WHOA! ThIS ONE Is lame aNd ONLY makes one sENTence", "WHOA! THiS One Is lAMe AnD onLY makes ONE SentenCe", "WHOA! THiS one is LAme anD oNLY MAKeS ONe SEnTENCE"] | |
d = FunnySentencesV2.new(BetterSentenceGenerator.new, UpCaser.new) | |
d.wacky_time! # => ["WHOA! DOUBLE YOUR PLEASURE.", "WHOA! TWO SENTENCES THIS TIME!", "WHOA! DOUBLE YOUR PLEASURE.", "WHOA! DOUBLE YOUR PLEASURE.", "WHOA! DOUBLE YOUR PLEASURE."] | |
e = FunnySentencesV2.new(LameSentenceGenerator.new, DownCaser.new) | |
e.wacky_time! # => ["WHOA! this one is lame and only makes one sentence", "WHOA! this one is lame and only makes one sentence", "WHOA! this one is lame and only makes one sentence", "WHOA! this one is lame and only makes one sentence", "WHOA! this one is lame and only makes one sentence"] | |
f = FunnySentencesV2.new(BetterSentenceGenerator.new, RandomCaser.new) | |
f.wacky_time! # => ["WHOA! Two seNTences ThIs tIME!", "WHOA! TWO seNTeNCEs ThIS tIMe!", "WHOA! TWo seNteNCeS THIs TimE!", "WHOA! TWo sentENceS ThIS TIMe!", "WHOA! DoUbLE YouR PLEASURE."] | |
# Now let's test our logic by mocking our generator to return a string we can test against | |
class GeneratorMock | |
def generate(number) | |
number.times.map { "This is a test sentence" } | |
end | |
end | |
test = FunnySentencesV2.new(GeneratorMock.new, UpCaser.new) | |
test.wacky_time! == ["WHOA! THIS IS A TEST SENTENCE", "WHOA! THIS IS A TEST SENTENCE", "WHOA! THIS IS A TEST SENTENCE", "WHOA! THIS IS A TEST SENTENCE", "WHOA! THIS IS A TEST SENTENCE", ] # => true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment