1

다음과 같이 다양한 유형의 이벤트가 있습니다. 일반적으로 나는 더 많은 사건이있다. 다음은 지도에서 공장 패턴을 동적으로로드하는 방법은 무엇입니까?

EventA 
EventB 
EventC 
EventD 
EventE 

내가 각 이벤트 유형 얻을 것이다 코드 : 각 이벤트에 대한

public void run() { 
    try { 
     while (!closed.get()) { 
     ConsumerRecords records = consumer.poll(10000); 
     // Handle new records 
     for (ConsumerRecord<String, String> record : records) { 
      GenericRecord payload = decoder.decode(record.value()); 
      String eventType = String.valueOf(payload.get("eventType")); 
      String eventMapHolder = String.valueOf(payload.get("eventMapHolder")); 
      Map<String, String> eventHolder = parseStringToMap(eventHolder); 
      // here eventType will "EventA", "EventB" and so on 
      // pass eventType to get the individual factory for that event type 
      // and then pass eventHolder to a particular method of that factory class which calls appropriate Query method. 
     } 
     } 
    } catch (Exception e) { 
     // log error 
    } 
    } 

을, 나는 다른 데이터베이스 쿼리 있지만이어야의 대부분을, 나는 하나의 데이터베이스를 수행 할 필요를 수행 할 필요가 모든 이들에게 공통적 인 쿼리. 예를 들어 :

    EventA -----> QueryA, QueryB 
        EventB -----> QueryA 
eventHolder   EventC -----> QueryA, QueryC 
        EventD -----> QueryA, QueryD 
        EventE -----> 
  • 은 그럼 그때 내가 eventHolder지도를 전달합니다, 나는 내 질문에이 코드에서 이벤트 유형으로 "EventA"를 얻을 가정 해 봅시다 : 아래
    EventA -----> QueryA, QueryB 
    EventB -----> QueryA 
    EventC -----> QueryA, QueryC 
    EventD -----> QueryA, QueryD 
    EventE -----> 
    

    는 흐름이 될 것입니다 메서드 (QueryA로 호출 해 봅시다)에이 메서드 내에서이 맵에서 일부 연산을 수행하고 새 Map을 반환합니다. 그리고 나서이 새로운 Map은 다른 메소드에 전달 될 것입니다 (QueryB를 호출 해 봅시다). 그리고 나서 우리는 그것에 대해 몇 가지 작업을 수행 한 다음 다른 Map을 반환 할 것이고 그 맵은 호출자에게 되돌아 갈 것입니다.
  • 이제 "EventB"가 내 질문에있는 코드에서 eventType으로오고, 다음으로 메소드에 eventHolder Map을 전달하고 (이 코드를 QueryA라고 부름),이 메소드에서이 맵에서 일부 작업을 수행한다고 가정 해 보겠습니다. 새로운지도를 반환하십시오. 그런 다음이지도가 호출자에게 다시 전달됩니다.
  • 이제 "EventE"가 내 질문에있는 코드에서 eventType으로 온다고 가정하고 eventHolder Map을 EventE 클래스에 전달하고이 경우에 할 일이 없기 때문에이 맵을 전달할 것입니다. 그것은 발신자에게 돌아온다.

질문 :

디자인 패턴 내가 이런 종류의 문제에 대한 사용해야합니까? 나는 if/else 또는 bcoz를 사용하지 않기를 바란다. 일반적으로 이벤트 유형이 많아서 eventType 값을 전달하여 런타임에 동적으로로드 할 수있는 개별 팩토리를 만들 생각이다.

미리 모든 이벤트 유형을 알고 있기 때문에 모든 팩토리를 맵에 배치하여 초기화 할 수 있으며 코드를 실행하는 동안 eventType이 오면 맵에서 개별 팩토리를로드 할 수 있습니다.

이 문제에 적합한 디자인 패턴 인 경우 여기에서 추상 팩토리 패턴을 사용하여이를 수행 할 수 있습니까? "eventType"을 해당 이벤트 유형의 인스턴스를 반환하는 팩토리의 키로 전달하고 싶습니다. 따라서 "EventA"을 팩토리에 전달한 다음 "EventA"에 대한 팩토리 클래스를 반환하면 내부적으로 QueryA 메서드를 호출하는 특정 클래스를 호출하고 QueryB 메서드를 호출하고 결국 Map을 반환합니다. 나는 위의 코드에서 그것을 출력 할 것이다. 다른 이벤트 유형에서도 마찬가지입니다.

나는이 사실에 대해 생각하고있었습니다. 이것이 공장 패턴으로 가능한지 확실하지 않거나 다른 디자인 패턴 일 수 있습니다.

EventFactory eventFactory = EventTypeFactory.getInstance().getFactory(eventType); 
Map<String, String> holder = eventFactory.execute(eventHolder); 
+0

if-else 나 switch를 사용하지 않고도 이것을 할 수있는 아주 좋은 방법을 알고 있었지만 기억이 안납니다. 아마 좋은 잠 후 아침에. – Reek

+0

반환 된지도의 목적은 무엇입니까? – Tony

답변

1

음,이 질문에 달성하기 위해 2 주 일이 있습니다.

  • 소개 & 사용자 지정 쿼리 논리를 다시 사용하십시오.
  • eventType 문자열을 관련 쿼리 동작에 동적으로 매핑합니다. 제일 먼저 들어

난 당신이 Interpreter 패턴의 변화를 채택 선호합니다. 그래서 이렇게 보일 것입니다. 메모리 풋 프린트를 피하기 위해 싱글해야한다 : 각 아이 쿼리 클래스 (QUERYA 전은)

public interface Query{ 
    public Map<String, String> execute(Map<String, String> map); 
} 

@Singleton 
public class QueryA implements Query{ 
    @Override 
    public Map<String, String> execute(Map<String, String> map){ 
    //queryA logic. 
    } 
}  

public class CustomQuery implements Query{ 
    List<Query> queryList; 

    public void CustomQuery(List<Query> queries){ 
    this.queryList = queries; 
    } 

    public void CustomQuery(Query query1, Query query2){ 
    this.queryList = new ArrayList(); 
    queryList.add(query1); 
    queryList.add(query2); 
    } 

    @Override 
    public Map<String, String> execute(Map<String, String> map){ 
    if(queryList == null){ 
     return map; 
    } 

    Map<String, String> eventMap = map; 
    for(Query query: queryList){ 
     eventMap = query.execute(eventMap); 
    } 
    return eventMap; 
    } 
} 

참고. 위에서 우리는 커스텀 질의 액션을 가질 수 있습니다.

예는 : QueryAB은 (

@Inject 
QueryA queryA; 
@Inject 
QueryB queryB; 
Query queryAB = new CustomQuery(queryA, queryB); 

지금 동적 필요한 QueryLogic에 당신의 이벤트 유형을 매핑하는 Map<String, Query> eventToQueryMap을 가질 수있다 (eventA에 필요한)의).

예 : 당신은 당신이 모든 수행 할 작업을 사용자의 이벤트 유형 문자열을받을 때마다

Map<String, Query> eventToQueryMap = new HashMap(); 
eventToQueryMap.put("EventA", queryAB); 
eventToQueryMap.put("EventB", queryA); 
//like above you can add for others too. 

는 그 다음이다.

이것은 주요 문제에 대한 개요 솔루션입니다. 사용자 정의를 직접 추가 할 수 있습니다. :))

0

내가 당신의 포인트를 얻는 경우에 확실하지 않다 (내 이름 지정 규칙이 엉망이 될 수도, 그냥 이름 아래 그와 함께했다). 이벤트를 처리하는 객체를 초기화하려면 팩토리 패턴이 한 번만 필요합니다.팩토리는 생성 패턴이며 쿼리 실행과 관련이 없습니다. 그래서 기본적으로 당신의 접근 방식은 부분적으로 올바른 :

Object o = EventTypeFactory.getInstance().getFactory(eventType);

이 공장이 사용할 수있는 포인트입니다. 우리는 이제 "이벤트 처리"에 가장 적합한 패턴을 논의 할 예정이므로 Object를 유형으로 사용하고 있습니다. 우선 그것은 행동 패턴이어야합니다. 커맨드 패턴이 도움이 될 것이라고 저는 말할 수 있습니다. 그러나 각 이벤트에 대해 잠재적으로 다른 양의 u 리를 나타 내기 위해 반복자 패턴이 필요할 수도 있습니다.

그러나 이런 식으로하는 것은 나에게는 과도한 잔인한 행동입니다. 나는 간단한 Template Method 패턴이 또한 당신이 필요로하는 결과를 가져올 것이라고 생각한다. 그러나 이는 조회 결과로 수행하려는 작업에 따라 다 (니다. 다음은 템플릿 방법의 예는 다음과 같습니다

public abstract class EventHandler { 
    public abstract Collection<String> getQueries(); 

    public Map<String, String> handleEvent(Map<String, String> eventData) { 
     Map<String, String> result = new HashMap<>(); 

     for(String query : getQueries()) { 
     // execute the query and merge the query result into the result map 
     } 

     return result; 
    } 
} 

public class EventAEventHandler extends EventHandler { 
    public abstract Collection<String> getQueries() { 
     List<String> queries = new ArrayList<>(); 

     queries.add("YourQueryHere"); 

     return queries; 
    } 
} 

가 이벤트를 처리하려면 :

EventHandler handler = EventTypeFactory.getInstance().getFactory(eventType); 
Map<String, String> holder = handler.execute(eventMap); 

것은 별도로 당신이 List<Map<String, String>>에 템플릿 메서드의 반환 형식을 변경할 수 있습니다 반환 된 각 쿼리에 대한 모든지도가 필요합니다.

+0

[here] (http://chat.stackoverflow.com/rooms/130322/factory-pattern-problem)에 대해 알아 보겠습니다. 나는이 접근법에 대해 약간 혼란 스럽다. 내가 정확히 무엇을하려고하는지 설명해 드리겠습니다. – john

0

내가 이해하는 한, 공장 패턴이 필요없는 것 같습니다. 당신은 다음과 같이 열거 할 수 있습니다 : 다음과 같은

public enum Event { 

    EventA { 
    @Override 
    Map<String, String> executeQuery() { 
     final Map<String, String> map = super.executeQuery(); 
     executeQueryB(); 
     return map; 
    } 

    private void executeQueryB() { 

    } 
    }, 
    EventB, 
    EventC, 
    EventD, 
    ; 

    Map<String, String> executeQuery() { 
    } 

} 

사용은 충분하다 :

return Event.valueOf("EventA").executeQuery(); 
+0

안녕하세요? 나는이 접근에 대해 약간 혼란 스럽다. 나는이 채팅방에있다. (http://chat.stackoverflow.com/rooms/130321/design-pattern-problem). 여기서 논의 해 보겠습니다. – john

관련 문제