Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
My attempt at an algorithm using a Template Method.
- Loading branch information
aimee daniells
committed
Mar 30, 2010
1 parent
459b003
commit 5249c19
Showing
5 changed files
with
73 additions
and
0 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
h2. Template Method | ||
|
||
bq. Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redifine certain steps of an algorithm without changing the algorithm's structure. | ||
|
||
I recently saw Jim Weirich show how the calculation of a square root could be refactored and generalised into an algorithm that can calculate any number by approximation and improving the estimate. | ||
|
||
The algorithm is basically this: guess a number. Improve the guess until it's good enough, and then return the guess. | ||
|
||
I thought this might be suitable for the template method. I have created an @ApproximationCalculator@ class which defines the general algorithm and provides a few methods that can be overridden when desired: @initial_guess@, @close_enough?@, @refine_guess@ and @final_answer@. | ||
|
||
The @SquareRootCalculator@ overrides three of the methods in order to define particular parts of the equation. |
21 changes: 21 additions & 0 deletions
21
behavioral_patterns/template_method/lib/approximation_calculator.rb
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
class ApproximationCalculator | ||
|
||
# template method | ||
def self.do_calculation(number) | ||
guess = initial_guess | ||
while !close_enough?(guess, number) | ||
guess = refine_guess(guess, number) | ||
end | ||
final_answer(guess) | ||
end | ||
|
||
# methods that can change | ||
def self.initial_guess; 1; end | ||
|
||
def self.close_enough?(guess, number); true; end | ||
|
||
def self.refine_guess(guess, number); guess + 1; end | ||
|
||
def self.final_answer(guess); guess; end | ||
|
||
end |
16 changes: 16 additions & 0 deletions
16
behavioral_patterns/template_method/lib/square_root_calculator.rb
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
require 'approximation_calculator' | ||
class SquareRootCalculator < ApproximationCalculator | ||
|
||
def self.close_enough?(guess, number) | ||
sprintf("%.5f", guess * guess) == sprintf("%.5f", number) | ||
end | ||
|
||
def self.refine_guess(guess, number) | ||
guess - (((guess ** 2) - number) / (2 * guess)).to_f | ||
end | ||
|
||
def self.final_answer(guess) | ||
((guess * (10 ** 5)).round) / (10 ** 5).to_f | ||
end | ||
|
||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib')) | ||
Dir[File.dirname(__FILE__) + '/lib/*.rb'].each {|file| require file } | ||
|
||
require 'test/unit' | ||
|
||
class TestTemplateMethod < Test::Unit::TestCase | ||
|
||
def test_square_root_of_9 | ||
assert_equal(3, SquareRootCalculator.do_calculation(9)) | ||
end | ||
|
||
def test_square_root_of_100 | ||
assert_equal(10, SquareRootCalculator.do_calculation(100)) | ||
end | ||
|
||
def test_square_root_of_1 | ||
assert_equal(1, SquareRootCalculator.do_calculation(1)) | ||
end | ||
|
||
def test_square_root_of_2 | ||
assert_equal(1.41421, SquareRootCalculator.do_calculation(2)) | ||
end | ||
|
||
end |