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


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.