2017-03-03 1 views
-1

저와 제 동료 중 하나는 다음과 같은 문제를 해결하기 위해 노력하고 있었다 :이것이 안티 패턴의 예입니까?

이 클래스의 예를 취할 수있는 내 동료 중 하나는 특정한 하나에서 하나 개의 속성을 가져 오기 A. 에서 하나 개의 특정 속성을 추출의 문제에 직면했다 클래스 (이 경우 A)는 쉽습니다. 그러나 은 여러 개의 클래스 (A1, A2 ...)를 가지고 있고 더 많은 코드 재사용으로이 클래스의 컬렉션에서 특정 속성을 가져 오려고한다고 가정합니다. 예를 들어

public class A { 
    private String name; 
    . 
    . 
    . 
} 
List<String> listOfNames = createNameList(listOfAInstances); 

createNameList() 메소드는 다음과 같이 될 것이다 :

List<String> tempList = new ArrayList<>(); 
for(A a : listOfAInstances) { 
    tempList.add(a.getName()); 
} 
return tempList; 

내가 각 클래스와 다른 속성에 대해이 작업을 수행해야 할 여러 클래스가 이제합니다.

  1. 반사 기반의 접근 방식 :

    나는 두 가지 방법을 제안했다.
  2. "PropertyExtractable"이라는 인터페이스를 만들고 그 안에 "extractProperty"라는 메서드를 넣습니다.

아래와 같이이 들어

interface PropertyExtractable { 
    Object extractProperty(); 
} 

public class A implements PropertyExtractable { 
    private String name; 
    . 
    . 
    . 
    public Object extractProperty() { 
     return this.name; 
    } 
} 

내가 다음 사방 즉,이 배경이었다

public Object getPropertiesOfPropertyExtractable(PropertyExtractable prExtractable) { 
     return prExtractable.extractProperty(); 
    } 

사용할 수있는 유틸리티 메소드를 작성할 수, 나의 다른 한 동료가 있었다 제 2 접근법에 대한 다른 견해, 그는 그것이 안티 패턴과 같다고 나에게 말했다. 그는 나에게 설명하려고 노력했다. 그러나 나는 그것을 그렇게 완전히 얻지 않았다. 그리고 그러므로 나는 여기에서 묻고있다.

이 예제를 Java의 Comparator 인터페이스와 비교하려고합니다. 자바와 마찬가지로 우리는 커스텀 객체 클래스에서 Comparator를 사용할 수 있으며 비교를위한 로직을 정의 할 수있다. 왜 추출 로직을 정의 할 수 없는가?

더 많은 인터페이스가이 방식으로 사용될 수있다. 우리는 그것을 사용해서는 안됩니다

나는이 접근 방식이 안티 패턴인지 알고 싶습니까? 왜?

+1

흠, 내 생각에 형식이 안전하지 않다는 것이 었습니다. 그런 다음 다른 클래스 목록을 가질 수 있다면 이미 공통 인터페이스를 가질 필요가 있습니다. 왜 거기에'String getName()'을 포함하지 않겠습니까? – Fildor

+1

예제 코드와 "예"텍스트가 클래스 이름과 일치하면 많은 도움이됩니다. –

+1

재정의 된 메소드에서보다 구체적인 리턴 유형을 사용할 수 있음을 잊지 마라 :'A'의'public String extractProperty()'. 그런 다음,'A'에 대한 참조가 있다면'String name = myA.extractProperty();'라고 쓸 수 있으며, 변환 할 필요가 없습니다. –

답변

0

당신은 별도의 방법으로 추출하는 코드를 삽입하고 다시 사용할 수 있습니다 :

class A { 
    private String name; 

    public String getName() { 
     return name; 
    } 
} 

class B { 
    private String surname; 

    public String getSurname() { 
     return surname; 
    } 
} 

public class SomeClass { 

    private <T> List<String> extractFields(List<T> list, Function<T, String> extractorFunction) { 
     return list.stream().map(extractorFunction).collect(Collectors.toList()); 
    } 

    public void someMethod() { 

     List<A> listOfInstancesA = new ArrayList<>(); 
     List<B> listOfInstancesB = new ArrayList<>(); 

     // fill lists 

     List<String> fieldsA = extractFields(listOfInstancesA, A::getName); 
     List<String> fieldsB = extractFields(listOfInstancesB, B::getSurname); 
    } 
} 
+0

이 질문을 게시 한 이유는 문제의 해결책을 찾는 것이 아니라 올바른 방법을 찾는 것입니다. 내가 언급했듯이 나는 이미이 두 가지 중 하나를 선택할 수있는 두 가지 접근 방식을 정의 했으므로 확실하게 작동 할 것입니다. –

+0

나의 제안은 반성도 아니고 인터페이스의 생성도 아니기 때문에 나는 이것을 제안했다. 초기 클래스 A와 B를 건드리지 않을 것입니다. –

+0

이 새로운 접근법에 대해 감사드립니다 :)하지만 좀 더 일반적인 문제로 보았습니다. 자바를 조금 사용했기 때문에 여기에서 Java를 사용했습니다. 그러나 똑같은 것이 Swift/JavaScript 또는 다른 언어. –

0

당신은 변경하지 않는 레거시 시스템과 협력하고 설명하는 상황.

공통 속성 (예 : Comparator 인터페이스의 예)에 대한 인터페이스를 소개하지 않으므로. 실제로 기능 인터페이스가 필요하기 때문에 안티 패턴 일 수있는 의미없는 인터페이스를 도입했습니다. PropertyExtractable vs. NamedObject => 메소드 : String getName()).

리플렉션을 구현하려는 경우 인터페이스는 정확할 수 있지만 표시되지 않습니다 (예 :귀하의 경우 이미 Reflection이 Java에 내장되어 있습니다.

일반적으로 어댑터 패턴을 사용하여 요청 된 인터페이스를 구현하지 않는 개체에서 속성/메서드를 가져옵니다.

+0

나는이 부분을 이해하지 못했습니다. "당신은 의미없는 인터페이스를 도입했습니다"그런 경우에 내가 찾아야 할 정확한 "의미"는 무엇입니까? –

+0

당신은 그러한 인터페이스의 사용이 보편적 인 추상화 수준으로 이동했습니다. 이것은 리플렉션을위한 메소드를 만들려고한다면 유스 케이스의 의미입니다. 리플렉션은 코드의 실제 구조 (객체, 클래스, 속성 등)에서 작동하기 때문에 괜찮습니다. 하지만 유스 케이스는 구체적인 도메인에서 파생 된 구체적인 (명명 된 객체) 사례입니다. 도메인의 공통 속성과 인터페이스 (예 : NamedObject Interface)를 파생시킬 수 있는지 여부를 찾아야합니다. – PsiX

+0

내 속성이 공통적이지는 않습니다 (일반적인 인터페이스로 이동할 수 없음). 그러나 호출 할 때 특정 속성 (이미 결정됨)을 반환 할 수있는 모든 클래스에서 공통된 동작을 원합니다. 전체 질문의 기초는 다음과 같습니다. 제 동료 중 한 명이 스위프트에서 8-10 클래스를 가지고 있기 때문에 화면에 표시 할 특정 속성을 추출하려고합니다 (드롭 다운 상태 일 수 있음). 그래서 제가 말했듯이, 두 가지 접근 방법, 즉 모든 구현이 속성을 얻는이 동작을 사용하도록하는 인터페이스의 반영/사용이 가능할 수 있습니다. –

관련 문제