2017-11-26 13 views
1

많은 행동이 있습니다. 모든 액션은 모든 액션에서 전달 된 일부 객체/컨텍스트에서 작동합니다. Strategy/Policy 패턴을 사용하고 싶습니다. 코 틀린에전략 - 인터페이스 유형별로 자동 등록

여기

입니다 예 :

interface Action { 
    val name: String 

    fun run(ctx: Context) 
} 

class Multiply: Action { 

    override name = "MULTIPLY" 

    override fun run(ctx: Context) { 
     writeToDb(ctx.id, ctx.number * 2) 
    } 
} 

class Substract 

class SendNotification 

etc... 

그래서 나는 시작시 모든 전략을 등록 할 수 있습니다. 그리고 Enum과 같은 구조에서 전략을 선택하십시오.

val action = selectAwaitingAction() 
val ctx = selectCtxById(action.transaction_id) 
perfromAction(ctx, actions.getByName(action.name)) 

fun performAction(ctx Context, action: Action) { 
    action.run(ctx) 
} 

제 질문은 인터페이스 유형별로 전략을 등록하는 방법입니다.

+0

확인합니다. 질문은 무엇입니까? 어서 해봐. – Vadim

+0

@ Vadim,이 구현에 붙어 있습니다. 내 말은 어떻게하면 모든 전략을 등록 할 수 있습니까? 인터페이스 – Sonique

+1

게시 한 코드가 Java가 아닙니다. 원하는 언어를 찾으십니까? – Bedla

답변

0

참고 : 이것은 완전한 예입니다. 인터페이스 유형별 자동 등록 만 찾고 있다면 대답의 마지막 부분으로 스크롤하십시오.

전략 디자인 패턴은 기능 테이블을 사용하여 구현할 수 있습니다. 이 구현은 Map<String,IImpl>에 저장됩니다. 여기서 key는 알고리즘의 이름이며, value는 알고리즘의 구현입니다.

일반적인 접근 방식 :

클래스 Context 인터페이스 Solver의 imlementations 공유 모든 매개 변수를 들고 고려한다.

public class Context extends HashMap<String,Object> { 
public <T> T get(String key, Class<T> resultClass){ 
    return resultClass.cast(get(key)); 
} 

public <T> T getOrDefault(String key, T def, Class<T> resultClass){ 
    return resultClass.cast(getOrDefault(key,def)); 
} 
} 

그리고 인터페이스 Solver 필요한 방법 solve

public interface Solver { 
void solve(Context context); 
String name(); 
} 

name 그런 다음 Solver 인터페이스 수정의 구현을 만들 수는 Context 객체를 공유했다. 이 예에서는 AddSolverMultiplySolver을 만들었습니다.

AddSolver.java :

public class AddSolver implements Solver { 

@Override 
public void solve(Context context) { 
    context.put("result", context.getOrDefault("result",0.0, Double.class) + context.get("add", Double.class)); 
} 

@Override 
public String name() { 
    return "+"; 
} 
} 

MultiplySolver.java

public class MultiplySolver implements Solver { 
@Override 
public void solve(Context context) { 
    context.put("result", context.getOrDefault("result",0.0, Double.class) * context.get("multiply", Double.class)); 
} 
@Override 
public String name() { 
    return "*"; 
} 
} 
Map<String,Solver> 의 수동 구성

: 인터페이스 Solver

구현이에 저장 될 수있다

@Test 
public void testCustomFunctionMap(){ 
    HashMap<String,Solver> functionMap = new HashMap<>(); 
    functionMap.put("+", new AddSolver()); 
    functionMap.put("*", new MultiplySolver()); 

    Context context = new Context(); 
    context.put("add", 2.0); 
    functionMap.get("+").solve(context); 
    TestCase.assertEquals(2.0, context.get("result", Double.class)); 

    context.put("multiply", 3.0); 
    functionMap.get("*").solve(context); 
    TestCase.assertEquals(6.0, context.get("result", Double.class)); 
} 

자동 Map<String,Solver>을 costruct 필요하면 더 접근이있다 Map<String,Solver>

의 자동 구성. 그들 중 많은 수가 this question에 언급되어 있습니다. 나는 org.reflections 라이브러리를 사용했다.

public class SolverScanner{ 
static HashMap<String, Solver> functionMap; 
static { 
     functionMap = new HashMap<>(); 
     Reflections reflections = new Reflections(SolverScanner.class.getPackage().getName()); 
     for(Class<? extends Solver> clazz : reflections.getSubTypesOf(Solver.class)){ 
      try { 
       Solver solver = clazz.newInstance(); 
       functionMap.put(solver.name(), solver); 
      } catch (Exception e) { 
       throw new IllegalStateException("Cannot construct functionMap",e); 
      } 
     } 
} 
public static HashMap<String, Solver> getFunctionMap(){ 
    return functionMap; 
} 
private SolverScanner(){}//disable instantiating 
} 

및 사용 : 그것은 가능하다

@Test 
public void testSolverScannerFunctionMap(){ 
    HashMap<String,Solver> functionMap = SolverScanner.getFunctionMap(); 

    Context context = new Context(); 
    context.put("add", 2.0); 
    functionMap.get("+").solve(context); 
    TestCase.assertEquals(2.0, context.get("result", Double.class)); 

    context.put("multiply", 3.0); 
    functionMap.get("*").solve(context); 
    TestCase.assertEquals(6.0, context.get("result", Double.class)); 
}