팩토리 패턴
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 # 호출자는 클래스 이름을 지정하지 않습니다챌린지
쉬움도형을 완성하고 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
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 Ruby 컴파일러