다음의 (안티) 패턴의 이름은 무엇입니까? 장점과 단점은 무엇입니까?


28

지난 몇 달 동안 나는 다음과 같은 기술 / 패턴에 대해 몇 번 걸려 넘어졌습니다. 그러나 특정 이름을 찾을 수 없으며 모든 장점과 단점에 대해 100 % 확신 할 수 없습니다.

패턴은 다음과 같습니다.

Java 인터페이스 내에서 일반적인 방법 세트는 평소와 같이 정의됩니다. 그러나 내부 클래스를 사용하면 인터페이스를 통해 기본 인스턴스가 누출됩니다.

public interface Vehicle {
    public void accelerate();
    public void decelerate();

    public static class Default {
         public static Vehicle getInstance() {
             return new Car(); // or use Spring to retrieve an instance
         }
    }
 }

나를 위해, 가장 큰 장점은 개발자가 인터페이스를 알아야하고 구현이 아닌 인터페이스에 대해서만 알아야한다는 것입니다. 예를 들어 인스턴스를 신속하게 생성하려는 경우.

 Vehicle someVehicle = Vehicle.Default.getInstance();
 someVehicle.accelerate();

또한 구성에 따라 인스턴스를 동적으로 제공하기 위해이 기술이 Spring과 함께 사용되는 것을 보았습니다. 이와 관련하여 모듈화에 도움이 될 수도 있습니다.

그럼에도 불구하고 인터페이스가 구현 중 하나와 연결되어 있기 때문에 이것이 인터페이스의 오용이라는 느낌을 떨칠 수 없습니다. (종속성 역전 원리 등) 누구든지이 기술의 장점과 단점뿐만 아니라이 기술이 어떻게 호출되는지 설명해 주시겠습니까?

최신 정보:

고려할 시간이 지난 후, 나는 다음 싱글 톤 버전의 패턴이 훨씬 더 자주 사용되었음을 다시 확인하고 알아 차렸다. 이 버전에서 공개 정적 인스턴스는 인터페이스가 마지막으로 필드가 한 번만 초기화되는 인터페이스를 통해 노출됩니다. 또한 인스턴스는 거의 항상 Spring 또는 일반 팩토리를 사용하여 검색하여 인터페이스를 구현에서 분리합니다.

public interface Vehicle {
      public void accelerate();
      public void decelerate();

      public static class Default {
           public static final Vehicle INSTANCE = getInstance();

           private static Vehicle getInstance() {
                return new Car(); // or use Spring/factory here
           }
      }
 }

 // Which allows to retrieve a singleton instance using...
 Vehicle someVehicle = Vehicle.Default.INSTANCE;

간단히 말해서 이것은 사용자 정의 싱글 톤 / 팩토리 패턴 인 것으로 보입니다.이 패턴은 기본적으로 인터페이스를 통해 인스턴스 또는 싱글 톤을 노출시킬 수 있습니다. 단점과 관련하여 아래 답변 및 의견에 몇 가지 이름이 지정되었습니다. 지금까지의 장점은 편의성에있는 것 같습니다.


어떤 종류의 싱글 톤 패턴?
Bryan Chen

인터페이스가 구현에 대해 "알지"말아야한다고 생각합니다. 아마 Vehicle.Default예를 들어, 팩토리 클래스와 같은 패키지 이름 공간들로 이동해야합니다 VehicleFactory.
augurar

7
그건 그렇고,Vehicle.Default.getInstance() != Vehicle.Default.getInstance()
Konrad Morawski

20
반 패턴은 여기서 동물 분석 반 패턴과 밀접한 관련이있는 자동차 분석 반 패턴을 사용합니다. 대부분의 소프트웨어에는 바퀴 나 다리가 없습니다.
피터 B

@PieterB : :-)))) 당신은 내 하루를 만들었다!
Doc Brown

답변:


24

Default.getInstanceIMHO는 매우 구체적인 형태의 팩토리 메소드 이며 싱글 톤 패턴 에서 가져온 명명 규칙과 혼합 되지만 후자의 구현은 아닙니다. 현재 폼에서 이것은 " 단일 책임 원칙 "에 위배됩니다 . 왜냐하면 인터페이스 (이미 클래스 API 선언의 목적을 제공하는 인터페이스)는 기본 인스턴스를 제공해야하는 추가적인 책임이 있기 때문입니다. VehicleFactory수업.

이 구조에 의해 야기되는 주요 문제점은 사이 순환 종속성을 유도한다는 것이다 Vehicle하고 Car. 예를 들어, 현재 양식 Vehicle에서는 한 라이브러리와 Car다른 라이브러리 에 배치 할 수 없습니다 . 별도의 팩토리 클래스를 사용하고 Default.getInstance메소드를 배치하면 해당 문제가 해결됩니다. 싱글 톤과 관련된 혼동을 막기 위해 해당 메소드에 다른 이름을 지정하는 것이 좋습니다. 결과는 다음과 같습니다.

VehicleFactory.createDefaultInstance()


답변 주셔서 감사합니다! 이 특정 예가 SRP를 위반 한 것에 동의합니다. 그러나 구현이 동적으로 검색되는 경우 여전히 위반인지 확실하지 않습니다. 예 를 들어 구성 파일에 의해 정의 된 특정 인스턴스를 검색하기 위해 Spring (또는 유사한 프레임 워크) 을 사용합니다.
Jérôme

1
@ Jérôme : IMHO라는 중첩되지 않은 클래스 VehicleFactory는 중첩 구조보다 더 일반적이며 Vehicle.Default, 특히 잘못된 "getInstance"메소드가 있습니다. Spring을 사용하여 순환 종속성을 피할 수는 있지만 개인적으로 상식 때문에 첫 번째 변형을 선호합니다. 그리고 여전히 공장을 다른 컴포넌트로 옮기는 옵션을 남겨두고 나중에 스프링없이 작동하도록 구현을 변경합니다.
Doc Brown

종종 클래스가 아닌 인터페이스를 사용하는 이유는 인터페이스 구현이 필요한 코드로 다른 목적을 가진 클래스를 사용할 수 있도록하기 위해서입니다. 기본 구현 클래스가 단순히 "정상"방식으로 인터페이스를 구현하는 무언가를 필요로하는 코드의 모든 요구를 충족시킬 수 있다면 인스턴스를 만드는 수단을 지정하는 것이 인터페이스에 유용한 것 같습니다.
supercat

Car가 매우 일반적인 표준 Vehicle 구현 인 경우 이는 SRP 위반이 아닙니다. Google이 autodrive()방법을 추가 할 때와 같이 차량에는 여전히 변경해야 할 이유가 한 가지뿐입니다 . 그런 다음 매우 일반적인 자동차는 예를 들어 NotImplementedException을 던져서 해당 메소드를 구현하도록 변경해야하지만 차량에서 변경해야 할 추가 이유는 없습니다 .
user949300

@ user949300 : SRP는 "수학적 증명 가능"개념이 아닙니다. 그리고 소프트웨어 설계 결정이 항상 "흑백"인 것은 아닙니다. 오리지널 코드는 그렇게 나쁘지는 않지만 물론 프로덕션 코드에서는 사용할 수 없으며 OP가 자신의 "업데이트"에서 언급 한 것처럼 편의성이 주기적 종속성을 능가하는 경우가 있습니다. 따라서 "별도의 팩토리 클래스를 사용하는 것이 더 나은 서비스를 제공하지 않으면 고려하십시오"라고 답하십시오. 또한 저자는 내가 대답 한 후에 원래의 질문을 약간 변경했습니다.
Doc Brown

3

이것은 나에게 Null Object 패턴 처럼 보입니다 .

그러나 그것은 Car클래스가 어떻게 구현 되는지에 달려 있습니다. 그것이 "중립적 인"방식으로 구현된다면, 그것은 분명히 Null 객체입니다. 즉, 인터페이스에서 모든 null 검사를 제거하고 각 발생 대신이 클래스의 인스턴스를 넣을 수 있으면 null코드가 여전히 올바르게 작동해야합니다.

또한이 패턴이라면 인터페이스 자체와 null 객체 구현간에 밀접한 연결을 만드는 데 아무런 문제가 없습니다. 널 인터페이스는 인터페이스가 사용되는 모든 곳에있을 수 있기 때문입니다.


2
답변 감사합니다. 제 경우에는 이것이 "Null Object"패턴을 구현하는 데 사용되지 않았다는 것이 확실하지만 흥미로운 설명입니다.
Jérôme
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.