Menu
Coddy logo textTech

팩토리 패턴

Coddy Ruby 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 43번째.

팩토리 패턴은 객체 생성을 한곳에 모읍니다. 호출자는 필요한 것을 이름으로 요청하는 경우가 많으며, 어떤 클래스가 생성되었는지 알 필요 없이 준비된 객체를 받습니다:

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를 사용하고, 삼각형에는 Math.sqrt(3) / 4 * size**2를 사용하세요. 팩토리는 고정된 해시 상수 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
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Ruby 컴파일러