Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نمط 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                           # المستدعي لا يسمي أبدًا صنفًا
challenge icon

التحدي

سهل

أكمل الأشكال وShapeFactory.create(kind, size). تشترك كل من Square وCircle وTriangle (متساوي الأضلاع) في الفئة الأساسية Shape، التي تُرجع to_s الخاصة بها square 3: area 9.00، مع كتابة اسم الفئة بأحرف صغيرة، والحجم والمساحة بمنزلتين عشريتين. استخدم 3.14159 لقيمة pi وMath.sqrt(3) / 4 * size**2 للمثلث. يبحث المصنع عن النوع في ثابت تجزئة مجمّد KINDS ويُرجع nil لنوع غير معروف.

يقرأ الكود الم provided الأسطر square 3، ويطلب من المصنع إنشاء كل شكل ويطبعه، أو يطبع unknown shape: hexagon.

ضع الكود الخاص بك في shape.rb وsquare.rb وcircle.rb وtriangle.rb وshape_factory.rb. يحتوي main.rb على كود الإدخال/الإخراج الم provided، ولا يمكن تعديله.

جرّب بنفسك

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
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Ruby عبر الإنترنت