프로토타입 은 객체들(복잡한 객체 포함)을 그의 특정 클래스들에 결합하지 않고 복제할 수 있도록 하는 생성 디자인 패턴입니다.
모든 프로토타입 클래스들은 객체들의 구상 클래스들을 알 수 없는 경우에도 해당 객체들을 복사할 수 있도록 하는 공통 인터페이스가 있어야 합니다. 프로토타입 객체들은 전체 복사본들을 생성할 수 있습니다. 왜냐하면 같은 클래스의 객체들은 서로의 비공개 필드들에 접근할 수 있기 때문입니다.
복잡도:
인기도:
사용 사례들: 프로토타입 패턴은 dup
또는 clone
메서드를 통해 루비에서 바로 사용할 수 있습니다.
식별: 프로토타입은 clone
또는 copy
등의 메서드들의 유무로 식별할 수 있습니다.
개념적인 예시
이 예시는 프로토타입 패턴의 구조를 보여주고 다음 질문에 중점을 둡니다:
패턴은 어떤 클래스들로 구성되어 있나요?
이 클래스들은 어떤 역할을 하나요?
패턴의 요소들은 어떻게 서로 연관되어 있나요?
main.rb: 개념적인 예시
# The example class that has cloning ability. We'll see how the values of field
# with different types will be cloned.
class Prototype
attr_accessor :primitive, :component, :circular_reference
def initialize
@primitive = nil
@component = nil
@circular_reference = nil
end
# @return [Prototype]
def clone
@component = deep_copy(@component)
# Cloning an object that has a nested object with backreference requires
# special treatment. After the cloning is completed, the nested object
# should point to the cloned object, instead of the original object.
@circular_reference = deep_copy(@circular_reference)
@circular_reference.prototype = self
deep_copy(self)
end
# deep_copy is the usual Marshalling hack to make a deep copy. But it's rather
# slow and inefficient, therefore, in real applications, use a special gem.
private def deep_copy(object)
Marshal.load(Marshal.dump(object))
end
end
class ComponentWithBackReference
attr_accessor :prototype
# @param [Prototype] prototype
def initialize(prototype)
@prototype = prototype
end
end
# The client code.
p1 = Prototype.new
p1.primitive = 245
p1.component = Time.now
p1.circular_reference = ComponentWithBackReference.new(p1)
p2 = p1.clone
if p1.primitive == p2.primitive
puts 'Primitive field values have been carried over to a clone. Yay!'
else
puts 'Primitive field values have not been copied. Booo!'
end
if p1.component.equal?(p2.component)
puts 'Simple component has not been cloned. Booo!'
else
puts 'Simple component has been cloned. Yay!'
end
if p1.circular_reference.equal?(p2.circular_reference)
puts 'Component with back reference has not been cloned. Booo!'
else
puts 'Component with back reference has been cloned. Yay!'
end
if p1.circular_reference.prototype.equal?(p2.circular_reference.prototype)
print 'Component with back reference is linked to original object. Booo!'
else
print 'Component with back reference is linked to the clone. Yay!'
end
output.txt: 실행 결과
Primitive field values have been carried over to a clone. Yay!
Simple component has been cloned. Yay!
Component with back reference has been cloned. Yay!
Component with back reference is linked to the clone. Yay!
다른 언어로 작성된 프로토타입