תבנית Factory
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Ruby של Coddy. שיעור 43 מתוך 57.
תבנית המפעל מרכזת את יצירת האובייקטים במקום אחד. הקוראים מבקשים את מה שהם צריכים, לעיתים קרובות לפי שם, ומקבלים אובייקט מוכן בלי לדעת איזו מחלקה נוצרה:
class Square
def initialize(side)
@side = side
end
def area
@side * @side
end
end
class Circle
def initialize(r)
@r = r
end
def area
(3.14159 * @r * @r).round(2)
end
end
class ShapeFactory
def self.create(kind, size)
case kind
when "square" then Square.new(size)
when "circle" then Circle.new(size)
end
end
end
puts ShapeFactory.create("square", 3).area
puts ShapeFactory.create("hexagon", 3).inspectפלט:
9
nilגיבוב שממפה שמות למחלקות הופך את המפעל לקצר יותר וקל יותר להרחבה. מחלקות הן אובייקטים, ולכן אפשר לאחסן אותן בגיבוב ולשלוח להן new:
class Dog
def speak
"Woof"
end
end
class Cat
def speak
"Meow"
end
end
class AnimalFactory
KINDS = { "dog" => Dog, "cat" => Cat }.freeze
def self.create(kind)
klass = KINDS.fetch(kind) { raise ArgumentError, "unknown animal: #{kind}" }
klass.new
end
end
puts AnimalFactory.create("cat").speak
begin
AnimalFactory.create("cow")
rescue ArgumentError => e
puts e.message
endפלט:
Meow
unknown animal: cowמפעל יכול גם לאפשר לקוד אחר לרשום סוגים חדשים בזמן ריצה, כך שהוספת סוג אינה מחייבת עריכה של המפעל:
class Plugins
@kinds = {}
class << self
def register(name, klass)
@kinds[name] = klass
end
def build(name)
@kinds.fetch(name).new
end
def names
@kinds.keys.sort
end
end
end
class Zip
def run
"zipping"
end
end
Plugins.register("zip", Zip)
puts Plugins.build("zip").run
p Plugins.namesפלט:
zipping
["zip"]הקוראים תלויים רק במה שהאובייקטים יכולים לעשות, כאן area או speak, ולא במחלקות הקונקרטיות. צורה חדשה פירושה מחלקה חדשה ורשומה חדשה אחת במפעל, ואין צורך לשנות שום דבר במקום אחר:
shape = ShapeFactory.create(kind, size) # Square, Circle, ...
puts shape.area # הקוד הקורא לעולם אינו מציין שם של מחלקהאתגר
קלהשלימו את הצורות ואת ShapeFactory.create(kind, size). Square, Circle ו־Triangle (שווה־צלעות) יורשות ממחלקת הבסיס Shape, שהמתודה to_s שלה מחזירה square 3: area 9.00, עם שם המחלקה באותיות קטנות, הגודל והשטח עם שתי ספרות אחרי הנקודה העשרונית. השתמשו ב־3.14159 עבור פאי וב־Math.sqrt(3) / 4 * size**2 עבור המשולש. המפעל מחפש את סוג הצורה בקבוע hash קפוא KINDS ומחזיר nil עבור סוג צורה לא מוכר.
הקוד שסופק קורא שורות square 3, מבקש מהמפעל ליצור כל צורה ומדפיס אותה, או unknown shape: hexagon.
כתבו את הקוד שלכם בקבצים shape.rb, square.rb, circle.rb, triangle.rb ו־shape_factory.rb. הקובץ main.rb מכיל את קוד הקלט/פלט שסופק ואסור לערוך אותו.
נסו בעצמכם
require_relative 'shape'
require_relative 'square'
require_relative 'circle'
require_relative 'triangle'
require_relative 'shape_factory'
# קוד קלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input = []
while (line = gets)
input << line.chomp
end
input.each do |line|
kind, size = line.split
shape = ShapeFactory.create(kind, size.to_f)
puts shape || "unknown shape: #{kind}"
end
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
3מתודות ומשתנים של מחלקה
מתודות של מחלקהמשתני מופע של מחלקהקבועיםמתודות ליצירת מופעיםסיכום – קודי קופוןתרגלו בעצמכם: קומפיילר Ruby אונליין