공장(객체 지향 프로그래밍)

Factory (object-oriented programming)
LePUS3의 공장공법

OOP(객체 지향 프로그래밍)에서, 공장은 다른 물체를 창조하기 위한 물체 – 형식적으로 공장은 어떤 메서드 콜로부터 다양한 프로토타입이나 클래스의[1] 물체를 반환하는 기능이나 방법이며, 이것은 "새로운"[a] 것으로 가정된다.보다 광범위하게, "새로운" 물체를 반환하는 서브루틴공장 방식이나 공장 기능에서와 같이 "공장"이라고 할 수 있다.이는 OOP에서 기본 개념으로, 여러 가지 관련 소프트웨어 설계 패턴의 기초를 이룬다.

동기

클래스 기반 프로그래밍에서 공장은 클래스 생성자추상화인 반면 프로토타입 기반 프로그래밍에서 공장은 프로토타입 객체의 추상화인 것이다.생성자는 단일 클래스의 인스턴스로서, 그리고 지정된 프로세스(분류 인스턴스화)에 의해 객체를 생성한다는 점에서 구체적이며, 공장은 다양한 클래스를 인스턴스화하거나 객체 풀과 같은 다른 할당 체계를 사용하여 객체를 생성할 수 있다.프로토타입 물체는 복제하여 물체를 만드는 데 사용되는 반면, 공장은 다양한 프로토타입을 복제하거나 다른 할당 체계에 의해 물체를 만들 수 있다는 점에서 구체적이다.

공장은 다양한 방법으로 시행될 수 있다.가장 흔히 하나의 방법으로 시행되는데, 이 경우 공장법이라고 한다.때로는 함수로 구현되기도 하는데, 이 경우 공장함수라고 한다.어떤 언어에서는 건설업자 자체가 공장이다.그러나 대부분의 언어에서는 그렇지 않고, 키워드를 사용하는 등 언어에 관용적인 방식으로 생성자를 호출한다.new, 공장은 특별한 상태를 가지고 있지 않으며, 일반적인 방법의 호출이나 기능 호출을 통해 호출된다.이러한 언어에서 공장은 건설업자의 추상화일 뿐, 건설업자가 그 자체가 공장이 아니기 때문에 엄격하게 일반화되지는 않는다.

용어.

공장의 개념 자체가 설계 패턴인지에 대해서는 용어가 다르다 - 설계 패턴에는 "공장 패턴"이 없고, 대신 공장을 사용하는 두 가지 패턴(공장 방식 패턴과 추상적인 공장 패턴)이 있다.반면 다른 사람들은 공장, 대부분은 종종factory 메서드 패턴을 사용한다 더 복잡한 패턴은 용어"팩토리 패턴"또는"공장 패턴"을 예약하고 idiom,[4]는 개념 자체 프로그래밍을 고려해 일부 소식통들은 개념에 공장 pattern,[2][3]로 이 문맥에서, 한 공장 자체의 개념에 s라고도 합니다 참조하십시오도레미파implectory.[4] 다른 맥락, 특히 파이톤 언어에서는 이 글에서와 같이 "공장" 그 자체가 사용된다.[5]좀 더 넓게 말하면, "공장"은 어떤 메서드 호출에서 물체를 반환하는 물체에만 적용되는 것이 아니라, (함수가 물체가 아니더라도) 공장 함수에서처럼 물체를 반환하는 서브루틴에도 적용될 수 있다.[6]많은 언어에서 공장은 방법을 호출하여 호출되기 때문에 공장에 대한 일반적인 개념은 특정한 공장 방식 패턴 설계 패턴과 혼동되는 경우가 많다.

사용하다

OOP는 메서드 디스패치에 의한 객체 사용다형성, 메서드가 호출되는 객체의 유형에 의해 결정되는 단일 디스패치를 통해 공식적으로 하위형 다형성을 제공한다.그러나, 생성자는 기존 객체를 사용하기보다는 어떤 유형의 객체를 생성하기 때문에, 이것은 생성자에게 효과가 없다.구체적으로는 건설업자를 부르면 어떤 대상을 파견할 것인지가 아직 없다.[b]

건설자나 프로토타입 대신 공장을 사용하면 객체 사용뿐만 아니라 객체 생성에도 다형성을 사용할 수 있다.구체적으로, 공장 사용은 캡슐화를 제공하며, 코드가 특정 클래스나 객체에 연결되지 않는다는 것을 의미하며, 따라서 클래스 계층이나 프로토타입은 그것을 사용하는 코드를 변경할 필요 없이 변경되거나 리팩터링될 수 있다 – 클래스 계층이나 프로토타입에서 추상화된다.

좀 더 기술적으로, 공장에서 시공자를 일반화하는 언어에서, 공장은 보통 시공자가 있을 수 있는 곳이라면 어디든 사용될 수 있다.[c] 즉, 시공자를 수용하는 인터페이스는 일반적으로 공장을 받아들일 수 있다. 즉, 분류와 인스턴스화를 지정할 필요 없이 오직 대상을 만드는 것만을 필요로 한다.

예를 들어 Python에서는collections.defaultdict클래스는[7] 유형 객체를 만드는 생성자를 가지고 있다.defaultdict[d] 그들의 기본값은 공장 호출에 의해 생산된다.공장은 건설업자에게 주장으로 전달되며, 그 자체로 건설업자나 건설업자처럼 행동하는 어떤 것, 즉 물건을 반환하는, 즉 공장을 반환하는 콜링 가능한 물체가 될 수 있다.예를 들어 다음과 같은 경우list리스트 생성자:

# collections.defaultdict([default_light[, ...]]) d = 채무 불이행(리스트를 작성하다) 

객체 생성

공장 객체는 특정 종류의 객체를 단순히 새로운 객체를 만드는 것보다 더 복잡한 프로세스, 특히 복잡한 할당이나 초기화를 원하는 경우에 사용된다.객체 생성에 필요한 프로세스 중에는 어떤 객체를 만들 것인가를 결정하는 것, 객체의 수명을 관리하는 것, 객체의 특화된 빌드업 및 해체 문제를 관리하는 것 등이 있다.공장 개체는 물체의 클래스를 동적으로 생성(해당되는 경우)하거나, 물체 풀에서 반환하거나, 물체에 대해 복잡한 구성을 수행하거나, 또는 다른 것을 결정할 수 있다.마찬가지로, 이 정의를 사용하여 싱글톤 패턴에 의해 구현된 싱글톤은 공식적인 공장이다. 즉, 물체를 반환하지만, 단일 인스턴스(instance)를 넘어서 새로운 물체를 생성하지는 않는다.

공장의 가장 간단한 예는 단순한 공장함수로, 시공자를 호출하기만 하면 결과를 반환한다.Python에서, 공장 기능f수업을 즉흥적으로 하는 것.A다음과 같이 구현될 수 있다.

반항하다 f():     돌아오다 A() 

싱글톤 패턴을 구현하는 간단한 공장 기능은 다음과 같다.

반항하다 f():     만일 f.오비지 이다 없음:         f.오비지 = A()     돌아오다 f.오비지  f.오비지 = 없음 

이렇게 하면 처음 호출될 때 객체가 생성되고 그 후에 항상 동일한 객체가 반환된다.

구문

공장은 다양한 방법으로, 가장 흔히 메서드 콜(공장 방식)으로 호출될 수 있으며, 때로는 공장이 콜링 가능한 물체(공장 기능)인 경우 함수로서 호출되는 경우도 있다.어떤 언어에서는 생성자와 공장이 동일한 구문을 가지고 있는 반면, 다른 언어에서는 생성자가 특별한 구문을 가지고 있다.Python, Perl, Ruby, Object Pascal, F#[e]처럼 건설자와 공장의 구문이 동일한 언어에서는 건설자를 공장으로 투명하게 대체할 수 있다.서로 다른 언어에서는 인터페이스에서 구분해야 하며, 시공자와 공장 간의 전환은 통화의 변경을 필요로 한다.

의미론

Java나 Python에서처럼 객체가 동적으로 할당되는 언어에서 공장은 의미론적으로 생성자와 동등하다.단, 일부 물체를 정적으로 할당할 수 있는 C++와 같은 언어에서, 공장들은 정적으로 할당된 계층의 생성자와는 다른데, 이는 후자가 컴파일 시간에 결정되는 메모리 할당을 가질 수 있는 반면, 공장의 반환 값 배분은 런타임에 결정되어야 하기 때문이다.만약 생성자가 함수에 대한 주장으로 전달될 수 있다면, 생성자의 호출과 반환 값의 배분은 런타임에 동적으로 이루어져야 하며, 따라서 공장을 호출하는 것과 유사하거나 동일한 의미론을 가져야 한다.

디자인 패턴

공장은 다양한 디자인 패턴, 특히 디자인 패턴 오브젝트 라이브러리와 같은 크리에이티브 패턴에 사용된다.이를 여러 언어로 구현하기 위해 구체적인 레시피가 개발됐다.예를 들어, "공장 방식 패턴", "빌더" 또는 "싱글톤"과 같은 몇 가지 "GoF 패턴"은 이 개념을 구현한 것이다.'추상적 공장 패턴'은 대신 공장 컬렉션을 만드는 방식이다.

어떤 설계 패턴에서, 공장 물체는 그것이 만들 수 있는 모든 종류의 물체에 대한 방법을 가지고 있다.이러한 메소드는 개체 생성 방법을 정의하는 매개 변수를 선택적으로 수용한 다음 생성된 개체를 반환한다.

적용들

공장 개체는 도서관 코드가 프레임워크를 사용하는 응용프로그램에 의해 하위 분류될 수 있는 유형의 개체를 생성해야 하는 툴킷과 프레임워크에서 공통적이다.그것들은 또한 시험 주도형 개발에 사용되어 수업이 시험 대상이 될 수 있다.[8]

공장은 실제로 만들어질 물체구체적인 유형을 결정하는데, 그 물체가 실제로 만들어지는 것은 바로 여기에 있다.공장에서는 객체에 추상적인 인터페이스만 반환하므로 클라이언트 코드는 방금 만들어진 객체의 실제 콘크리트 타입을 알 수 없고 부담도 없다.그러나 콘크리트 물체의 종류는 추상공장에 의해 알려져 있다.특히 이는 다음을 의미한다.

  • 클라이언트 코드는 콘크리트 유형에 대해 전혀 알지 못하므로 콘크리트 유형과 관련된 헤더 파일이나 클래스 선언을 포함할 필요가 없다.클라이언트 코드는 추상적인 유형만을 다룬다.콘크리트 타입의 물체는 공장에서 실제로 만들어지지만 클라이언트 코드는 추상적인 인터페이스를 통해서만 그러한 물체에 접근한다.
  • 새로운 콘크리트 타입을 추가하는 것은 클라이언트 코드를 다른 공장을 사용하도록 수정하는 것으로, 일반적으로 한 파일에 한 줄씩 수정한다.이는 새로운 유형을 인스턴스화하기 위해 클라이언트 코드를 수정하는 것보다 훨씬 더 쉬우며, 새 개체가 생성되는 코드의 모든 위치를 변경해야 한다.

적용가능성

다음과 같은 경우에 공장을 사용할 수 있다.

  1. 개체의 생성은 코드를 크게 복제하지 않으면 재사용이 불가능하게 만든다.
  2. 객체를 생성하려면 Composing class에 포함되지 않아야 하는 정보나 자원에 대한 접근이 필요하다.
  3. 생성된 개체의 수명 관리는 애플리케이션 내에서 일관된 동작을 보장하도록 중앙 집중화되어야 한다.

공장, 특히 공장 방식은 툴킷프레임워크에서 흔히 볼 수 있는데, 여기서 도서관 코드는 프레임워크를 사용하는 어플리케이션에 의해 하위 분류될 수 있는 유형의 객체를 생성해야 한다.

병렬 클래스 계층 구조는 종종 한 계층의 객체가 다른 계층으로부터 적절한 객체를 만들 수 있어야 한다.

시험 주도형 개발에서는 공장 방법을 사용하여 수업을 시험할 수 있다.[9]만약 그런 클래스라면Foo다른 대상을 생성하다Dangerous자동화된 단위 테스트(항상 사용할 수 없는 프로덕션 데이터베이스와 통신하는 경우)에 넣을 수 없는 다음Dangerous개체가 가상 공장 방법에 배치됨createDangerous수업 중인Foo. 테스트를 위해,TestFoo(의 하위 클래스)Foo그런 다음 가상 공장 방법을 사용하여 )가 생성됨createDangerous생성 및 반환을 위해 재정의됨FakeDangerous, 가짜 물건.단위 테스트 후 사용TestFoo의 기능을 테스트하다Foo실물을 사용하는 부작용 없이.Dangerous이의를 제기하다

장점과 변종

디자인 패턴에서 사용하는 것 외에도 공장, 특히 공장 방식은 다양한 이점과 변화를 가지고 있다.

기술명

공장법은 이름이 뚜렷하다.많은 객체지향 언어에서 생성자는 자신이 속한 클래스와 이름이 같아야 하는데, 이는 물체를 만드는 방법이 하나 이상 있을 경우(과부하 참조) 모호성을 초래할 수 있다.공장 방법은 그러한 제약이 없고 기술명을 가질 수 있다; 이것들은 때때로 대체 시공자로 알려져 있다.예를 들어, 두 개의 실수로 복잡한 숫자가 생성되면 실수는 데카르트 좌표나 극좌표로 해석할 수 있지만, 공장법을 사용하면 C#의 다음 예에서 예시한 바와 같이 의미가 명확하다.

    공중의 계급 콤플렉스     {         공중의 곱절로 하다 진짜;         공중의 곱절로 하다 가상의;          공중의 정태의 콤플렉스 프로프카르테시안(곱절로 하다 진짜, 곱절로 하다 가상의)         {             돌아오다 새로운 콤플렉스(진짜, 가상의);         }          공중의 정태의 콤플렉스 프롬폴라(곱절로 하다 계통, 곱절로 하다 )         {             돌아오다 새로운 콤플렉스(계통 * 수학.코스(), 계통 * 수학.());         }          사유의 콤플렉스(곱절로 하다 진짜, 곱절로 하다 가상의)         {             .진짜 = 진짜;             .가상의 = 가상의;         }     }  콤플렉스 상품 = 콤플렉스.프롬폴라(1, 수학.PI); 

이와 같은 해체를 위해 공장법을 사용할 때, 원시 건설업자들은 종종 사적으로 만들어 고객들에게 공장법을 사용하도록 강요한다.

캡슐화

공장 방법은 물체의 창조를 캡슐화한다.이는 생성 프로세스가 매우 복잡한 경우, 예를 들어 구성 파일의 설정이나 사용자 입력에 따라 달라지는 경우 유용할 수 있다.

이미지 파일을 읽는 프로그램을 예로 들어보자.이 프로그램은 각 형식에 대한 판독기 클래스로 대표되는 서로 다른 이미지 형식을 지원한다.

프로그램이 이미지를 읽을 때마다 파일의 일부 정보를 바탕으로 적절한 유형의 판독기를 만들어야 한다.이 논리는 공장식으로 캡슐화할 수 있다.이 접근방식은 Simple Factory라고도 한다.

자바

공중의 계급 ImageReaderFactory {     공중의 정태의 ImageReader createImageReader(ImageInputStreamProcessor 이이스프) {         만일 (이이스프.아이지프()) {             돌아오다 새로운 GifReader(이이스프.getInputStream());         }         다른 만일 (이이스프.isJPEG()) {             돌아오다 새로운 JpegReader(이이스프.getInputStream());         }         다른 {             던지다 새로운 언페러그먼트예외("알 수 없는 이미지 유형.");         }     } } 

PHP

계급 공장  {     공중의 정태의 기능을 발휘하다 짓다($type)     {         $class = "형식" . $type;         만일 (!class_class($class)) {             던지다 새로운 예외("형식 클래스 누락.");         }         돌아오다 새로운 $class;     } }  접점 FormatInterface {}  계급 FormatString 기구들 FormatInterface {} 계급 FormatNumber 기구들 FormatInterface {}  해보다 {     달러 끈 = 공장 ::짓다("끈"); } 잡히다 (예외 $e) {     메아리치다 $e->getMessage(); }  해보다 {     달러 수 = 공장 ::짓다("숫자"); } 잡히다 (예외 $e) {     메아리치다 $e->getMessage(); } 

제한 사항

공장법의 사용과 관련된 세 가지 제한이 있다.첫 번째는 기존 코드를 리팩터링하는 것과 관련이 있고, 다른 두 가지는 클래스를 확장하는 것과 관련이 있다.

  • 첫 번째 제한은 공장을 이용하기 위해 기존 클래스를 리팩터링하는 것이 기존 고객을 무너뜨린다는 것이다.예를 들어, 콤플렉스 클래스가 표준 클래스라면 다음과 같은 코드를 가진 수많은 클라이언트를 가질 수 있다.
    콤플렉스 c = 새로운 콤플렉스(-1, 0); 
일단 서로 다른 두 개의 공장이 필요하다는 것을 깨닫는 순간, 우리는 (에서 보여진 코드로) 클래스를 바꾼다.그러나 현재 생성자가 비공개이기 때문에 기존 클라이언트 코드는 더 이상 컴파일되지 않는다.
  • 두 번째 제한은 패턴이 민간 시공자 사용에 의존하기 때문에 클래스를 확장할 수 없다는 점이다.하위 클래스는 반드시 상속된 생성자를 호출해야 하지만, 생성자가 비공개인 경우에는 이 작업을 수행할 수 없다.
  • 세 번째 제한사항은 클래스를 확장해야 하는 경우(예: 시공자를 보호하도록 함으로써), 하위 클래스는 정확하게 동일한 서명으로 모든 공장 방법에 대한 자체적인 재이행을 제공해야 한다는 것이다.예를 들어, if class는StrangeComplex연장하다Complex, 만약 그렇지 않다면.StrangeComplex모든 공장 방법의 자체 버전인 통화 제공
    스트레인지콤플렉스.프롬폴라(1, 수학.파이); 
    의 예가 될 것이다.Complex(수퍼클래스) 하위 클래스의 예상 인스턴스보다는일부 언어의 반영 특징은 이 문제를 피할 수 있다.

세 가지 문제 모두 기본 프로그래밍 언어를 변경하여 공장을 일급 구성원으로 만들면 완화될 수 있다(가상 클래스 참조).[10]

메모들

  1. ^ 인터페이스상으로는 어떤 물체를 반환하는 물체를 공장으로 사용할 수 있지만 의미론적으로 공장에서는 클래스 인스턴스(instance)나 프로토타입의 복사본과 같이 새로 생성된 물체나 물체 풀에서 재초기화된 물체처럼 새것처럼 보이는 물체를 반환한다.
  2. ^ 생성자 자체가 클래스 객체(클래스 방식)에 메서드인 언어에는 기존 객체가 있고, 생성자는 공장 방식의 특별한 경우로서 다형성 생성은 다형성 방법 디스패치의 특별한 경우다.다른 언어에서는 시공자와 방법의 구분이 뚜렷하다.
  3. ^ 건설업자는 특별한 경우이기 때문에 공장이 할 수 있는 곳이면 어디든 사용할 수 있다.
  4. ^ 이 수업은 의 하위 수업이다.dict, 매핑 또는 사전의 기본 제공 파이썬 구현.
  5. ^ 선택 키워드일 경우new누락되다

참조

  1. ^ Gamma, Erich (1994). Design Patterns. Addison-Wesley. pp. 18–19. ISBN 9780321700698.
  2. ^ "공장 패턴", OODesign.com
  3. ^ 공장 패턴, WikiWikiWeb
  4. ^ a b 제4장. 공장 패턴: OO도덕으로 굽기:단순 공장 정의
  5. ^ "30.8 클래스는 대상: Generic Object Factorys", Learning Python, Mark Lutz, 4번째 판, O'Reilly Media, Inc., ISBN 978-0-596-15806-4
  6. ^ 공장 방법, WikiWikiWeb
  7. ^ defaultdict 객체
  8. ^ Feathers, Michael (October 2004). Working Effectively with Legacy Code. Upper Saddle River, NJ: Prentice Hall Professional Technical Reference. ISBN 978-0-13-117705-5.
  9. ^ Feathers, Michael (October 2004), Working Effectively with Legacy Code, Upper Saddle River, NJ: Prentice Hall Professional Technical Reference, ISBN 978-0-13-117705-5
  10. ^ Agerbo, Ellen; Cornils, Aino (1998). "How to preserve the benefits of design patterns". Conference on Object Oriented Programming Systems Languages and Applications. Vancouver, British Columbia, Canada: ACM: 134–143. ISBN 1-58113-005-8.