2010-02-03 5 views
3

지난 몇 달 전 저는 독립 소프트웨어 개발 회사의 대표 두 명이 주최 한 프리젠 테이션에 참석했습니다. 주로 좋은 소프트웨어 디자인과 관행에 관한 것이 었습니다.생성자 대신 getInstanceOf를 사용하는 경우

두 사람은 자바에 대해 주로 이야기하고 나는 그들이 어떤 상황에서 대신 생성자의) getInstanceOf를 (사용하는 아주 좋은 방법이라고 말을 기억한다. 그것은 항상 생성자가 아닌 다른 클래스에서 getInstanceOf()를 호출하는 것과 관련이 있으며 대규모 프로젝트에서 훨씬 더 나은 접근 방법이었습니다.

당신은 내가 지금부터 많이 기억할 수없는 볼 수 있듯이 : /하지만 나는 그들이 사용되는 인수가 정말 설득력이 있다고 기억한다. 당신 중 누구도 그런 디자인을 접하게 된 것이 아닌가하는 의문이들 것입니다. 아니면 전혀 그렇지 않다고 생각하니?

+0

나는 당신이 사용하는 것이 어떤 맥락에서 확실하지 않다. Common은 Class.forName ("org.apache.derby.jdbc.EmbeddedDriver"); db 드라이버를로드하는 경우 – stacker

+0

다른 응답자의 아이디어가 맞는지 확실하지 않습니다. 클래스에 대한 팩토리 메서드를 사용하는 것과 'new'로 직접 인스턴스화하는 것에 대해 정말로 이야기하고 있습니까? 또는 다른 것? – PSpeed

답변

7

. 이러한 생성자를 통해 getInstanceOf()new을 사용하는 등 방법의 몇 가지 장점에

. 수 static 팩토리 방법 ...

  1. 하는 그와 같은 특성 및 다른 목적/싱글, 또는 환경 조건에 기초하여 (일부 경우에 바람직한 경우, 기본 클래스는 다른 서브 클래스를 생성하고자 메소드 매개 변수).

  2. 기존 개체를 만드는 대신 기존 개체를 반환하도록 선택하십시오. 이에 대한 예는 Java API의 Boolean.valueOf(boolean)을 참조하십시오.

  3. 생성자와 같은 일을 할 - 단지 클래스 자체의 새로운 인스턴스를 돌려줍니다.

  4. 새 개체를 생성하는 데 여러 가지 방법을 제공하고 이러한 메서드의 이름을 덜 혼동스럽게 만들 수 있습니다 (예 : 생성자와 함께 시도해보십시오. 곧 많은 오버로드가 발생합니다). 두 가지 방법으로 인스턴스를 생성 할 수 있어야하지만 동일한 유형의 매개 변수 만 필요로하는 경우에는 생성자와 함께이 작업을 수행 할 수도 없습니다.예 :

    // This class will not compile! 
    public class MyClass { 
        public MyClass(String name, int max) { 
         //init here 
        } 
        public MyClass(String name, int age) { 
         // init here 
        } 
    } 
    
    // This class will compile. 
    public class MyClass2 { 
        private MyClass2() { 
        } 
        public static MyClass2 getInstanceOfMax(String name, int max) { 
         MyClass2 m2 = new MyClass2(); 
         // init here 
         return m2; 
        } 
        public static MyClass2 getInstanceOfAge(String name, int age) { 
         MyClass2 m2 = new MyClass2(); 
         // init here 
         return m2; 
        } 
    } 
    
  5. 위의 조합을 수행.

  6. , 그것은 다른 클래스의 인스턴스를 인스턴스의 세부 사항을 숨긴다 그래서 미래 (건축 캡슐화)으로 변형 될 수있는 모든 위에.

생성자는 요청 된 정확한 유형의 개체의 새 인스턴스 만 만들 수 있습니다. 나중에 변경할 수 없습니다.

이 패턴의 일부 단점

은 다음과 같습니다

  1. 공장 방법은 정적 그래서 하위 클래스에 상속 될 수 없습니다; 상위 생성자는 하위 클래스에 쉽게 액세스 할 수 있습니다.

  2. 팩토리 메소드 이름은 다양 할 수 있으며 이것은 몇 가지 (신규) 개발자를위한 혼란 스러울 수 있습니다.

개인적인 경험을 요구했습니다. 네, 저는 두 패턴을 자주 사용합니다. 대부분의 클래스 생성자에 대해서는 훨씬 더 고급 요구가있을 때 정적 팩토리를 사용합니다. 또한 다른 언어 (독점적이지만 자바와 비슷 함)로 프로젝트를 진행하며, 이러한 형태의 건설이 의무화됩니다.

1

나는 당신이 클래스 클래스에 newInstance method을 의미 생각한다. MyClass foo = MyClass.newInstance();

이 개체 인스턴스화 형식은 creational patterns에서 많이 사용됩니다. 속성 또는 XML 파일에서와 같이 객체 의 구체 런타임 유형을 외부에서과 같이 지정하려는 경우에 유용합니다. 드류가 옳다면

+0

그러나 :이 선언되지 않은 체크 된 예외를 던질 수있는'에 Class.newInstance()는'악이다. 'InvocationTargetException'을 던지는'Constructor.newInstance()'를 사용하는 것이 더 나을 수도 있습니다. http://stackoverflow.com/questions/195321/why-is-class-newinstance-evil를 참조 –

+0

@ 사이먼 Nickerson을 -이 좋은, 통찰력있는 정보입니다. 하지만 실제로 newInstance()가 "악"하다고 확신하지는 않습니다. Java의 컴파일 타임 예외 검사가 중요한지 아닌지에 대한 결정을 내릴 수 있습니다. 나는 이것이 합리적인 사람들이 동의하지 않는 영역 중 하나라는 것을 알고 있지만, 나 자신은 팬이 아니다 (신호를 나 빠진다 : 소스 코드의 잡음 비율). Groovy는 Groovy 코드가 개인용 메소드를 공용으로 취급하여 "기능"으로 취급한다는 사실을 커뮤니티가 생각합니다. 당신이 자바의 동의 –

+0

여부가 예외를 체크'에 Class.newInstance()'의 행동은 확실히 놀라운 일이다. Evil은 아마도 약간 강하다. :) 그러나 나는 이것이 체크 된 예외 메카니즘을 이런 방식으로 파괴하는 것을 허용하는 것이 실수 였다고 생각한다. –

1

newInstance()는 자바 리플렉션 API의 일부입니다. 따라서 생성자를 사용하는 것만 큼 자연스럽지 않습니다.

큰 프로젝트에서 사용하는 것이 바람직한 이유는 그것이 Java Bean programming style으로 연결된다는 것이고 분명히 개체를 특정하게 만드는 것입니다. 대형 프로젝트의 경우 오브젝트를 생성하는 것이 교차 관심사가 아니라 오히려 한 소스/공장에서 명확하게 식별 된 책임이어야합니다. 그러나 IMHO, 당신은 그 모든 이점을 얻고 더 많은 것을 IoC pattern으로 얻습니다.

관련 문제