2012-02-14 1 views
4

현재 Java에서 약 30 개의 다른 매개 변수를 입력해야하는 시뮬레이션을 구현 중입니다. 결국, 파일과 GUI에서이 매개 변수를 읽을 수 있기를 원하지만, 지금은 파일 입력에만 초점을 맞추고 있습니다. 내 시뮬레이션에는 다른 유형의 매개 변수가 필요합니다. 문자열, int 및 복식이며 현재 시뮬레이션을위한 필드로 사용하고 있습니다.Java에서 변수 유형을 사용하여 매개 변수 관리를 효율적으로 코딩

private String simName; 
private int initialPopulationSize; 
private double replacementRate; 

이러한 매개 변수 내가 배열에 저장할 수없는 모두 같은 유형이 아니며 내가 따로 코드의 약 30 배를 같은 종류를 사용하여 하나 하나를 읽을 수 있기 때문에. 세 개의 매개 변수의 예 :

//scanner set up and reading each line, looking for "(key)=(param)" regex matches 
//if statement to check each param name against the key matched in file. Store param in that field if the name matches. 
String key = m.group(1); 
if (key.equals(PKEY_SIM_NAME)) { 
    if (simNameSet) { 
     throw new IllegalStateException("multiple values for simulation name"); 
    } 
    this.simName = m.group(2); 
    simNameSet = true; 

} else if (key.equals(PKEY_INITIAL_SIZE)) { 
    if (initialSizeSet) { 
     throw new IllegalStateException("multiple values for initial population size"); 
    } 
    this.initialPopulationSize = Integer.parseInt(m.group(2)); 
    initialPopulationSize = true; 

} else if (key.equals(PKEY_MUT_REPLACEMENT)) { 
    if (replacementRateSet) { 
     throw new IllegalStateException("multiple values for replacement rate"); 
    } 
    this.replacementRate = Double.parseDouble(m.group(2)); 
    replacementRateSet = true; 
} 
    //Add nauseum for each parameter..... 

그래서 나는 현재 매개 변수를 읽기 위해 길고 unweildly 방법이 있고, 나는 가능성이 GUI에서 읽기 위해 다시 동일한 작업을 수행해야합니다.

제가 생각한 최선의 대안은 모든 것을 String 필드로 먼저 읽는 것입니다. 그렇게하면지도를 사용하여 읽는 간단한 몇 줄을 쓸 수 있습니다. 이 (테스트되지 않은 코드) 같은 것을 : 그것은 내가 사용하여 원하는 목적지 나는 비 문자열 PARAMS 캐스팅 할 때마다 것 때문에지도에서 이러한 매개 변수를 사용하여 올 때

//This time with a paramMap<String, String>, scanner set up as before 
if (!paramMap.containsKey(key)) { 
    paramMap.put(key, m.group(2)); 
} 
else{ 
    throw new IllegalStateException("multiple values for initial population size"); 
} 

그러나이 불편 될 것입니다 그들.

이 시점에서 나는 이것이 내 최선의 접근 방법이라고 생각합니다. 내가 경험하기 전에 좀 더 경험이 많은 사람이 이런 상황을 처리하기위한 더 나은 전략을 제시 할 수 있는지 알고 싶습니다.

+0

30 개의 매개 변수를 개별 개체로 재구성 할 수 있습니까? Spring을 사용하는 접근법을 살펴보십시오. 여기서 매개 변수를 xml 파일에 넣을 수 있습니다.이 매개 변수는 각 매개 변수의 객체 유형을 언급하고 Spring에 의존하여 Bean에로드합니다. 훨씬 더 깔끔하게. 물론 입력 구성 파일의 구조를 제어 할 수 없다면이 아이디어는 유용하지 않을 수 있습니다. –

+0

이것은 내가 생각하지 못한 것입니다. 그러나 의도적으로 입력 파일을 가능한 한 단순하게 만들었습니다. (문자순으로 각 줄마다 [key] = [value] 만 입력하면됩니다.) 따라서 누구나 자신의 시뮬레이션을 만들 수 있습니다. 그러나 일단 gui (사용자가 자신의 파일을 만드는 대신 gui 만 사용할 수 있다고 가정하면) 이것은 매개 변수 집합을 저장하기위한 좋은 옵션이 될 수 있으므로 시뮬레이션을 신속하게 다시로드 할 수 있습니다. – MattLBeck

답변

1

: 매개 변수의 각 유형에 대한

interface Parameter { 
    void parse(String s); 
    Object getValue(); 
    ... 
} 

및 클래스를 당신은 갖고 싶어한다. IntParameter, DoubleParameter, StringParameter. 여기에 IntParameter의 스케치입니다 :

class IntParameter implements Parameter { 
    private int value; 

    public void parse(String s) { 
     value = Integer.parseInt(s); 
    } 

    public Object getValue() { 
     return value; 
    } 
    ... 
} 

그런 다음 당신은 Map<String, Parameter>에 매개 변수를 저장하고 명령 줄 옵션 또는 속성과 같은 다양한 소스에서 채울 수 있습니다. 당신은 매개 변수 객체의 값을 저장하지만 매개 변수를 자신의 값에 액세스하는 데 사용되는 정적 객체를하지 않는 경우


더 형식 안전하지만 복잡한 솔루션

달성 할 수있다. 이 다음 예제에 설명되어이 허용

abstract class Parameter { 
    private String name; 

    public Parameter(String name) { 
     this.name = name; 
    } 

    public abstract Object parse(String s); 
} 

class IntParameter extends Parameter { 
    public static final IntParameter ANSWER = new IntParameter("answer"); 
    // Add more options here. 

    public IntParameter(String name) { super(name); } 

    public Object parse(String s) { 
     return Integer.parseInt(s); 
    } 
} 

class Parameters { 
    private Map<Parameter, Object> params = new HashMap<Parameter, Object>(); 

    public int get(IntParameter p) { 
     return (Integer)params.get(p); 
    } 

    public void put(IntParameter p, int value) { 
     params.put(p, value); 
    } 

    public void putString(Parameter p, String value) { 
     params.put(p, p.parse(value)); 
    } 
} 

당신은 유형 안전한 방식으로 매개 변수를 액세스 할 수 :

Parameters params = new Parameters(); 
params.putString(IntParameter.ANSWER, "42"); // parse and store the value 
int value = p.get(IntParameter.ANSWER); 

솔루션

는 다른 종류의 확장 할 수 있습니다.

+1

이 방법은 매우 좋기 때문에 매우 기분이 좋습니다.하지만 여전히 모든 getValue를 구체적으로 캐스팅해야하는 것과 같은 문제가있는 것 같습니다.) 호출 (문자열 매개 변수도 역시 캐스팅해야하기 때문에 더욱 그렇다). 그러나 Map에 모든 것을 저장하는 좋은 방법 중 하나이므로 비슷한 것을 구현할 수 있습니다. 감사! – MattLBeck

+0

@kikimbob : Cast를 피하려면 Preferences API와 마찬가지로 Parameter 클래스에서 getValue 대신 getInt, getDouble 및 getString을 사용할 수 있습니다. – vitaut

+0

매개 변수 HashMap에 매개 변수의 하위 클래스를 저장하지 않는다면 어쨌든 IntParamter에 대해 캐스팅해야한다는 뜻입니까? :/ – MattLBeck

0

상황에 맞는 속성 파일을 사용할 수 있습니다. 특성 파일은 키/v 쌍 쌍으로 구성됩니다. 이 approch를위한 좋은 유틸리티는 스프링을 사용하는 것입니다. 샘플 : 당신의 키-1 키 persistenceXmlLocations 회원의

<bean id="pum" 
      class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager"> 
     <property name="persistenceXmlLocations" value="${your-key-1}"/> 
    </bean> 

봄 설정 값 :

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 

     <property name="locations"> 
        <list> 
        <value>[your-path-1]</value/> 
        <value>[your-path-2]</value/> 
        </list> 
     </property> 
    </bean> 

및 읽기 키/값

. 스프링을 사용하면 좋은 점은 입니다. 캐스팅, 스프링이 고유 한 유형의 속성을 다양한 유형으로 캐스팅합니다.

+0

봄과 콩에 관해서는 거의 알지 못합니다. 이것은 입력 파일에 사용할 형식입니까, 아니면 정의 할 수있는 일종의 XML 클래스입니까? – MattLBeck

+0

예, placeHolderConfigurer의 위치 속성으로 입력 파일을 지정할 수 있습니다. 나는 XML 목표가 더 효과가 있어야한다고 생각한다. – MJM

2

그런 파일을 구문 분석하는 것은 처음에는 좋지 않습니다. 그것은 이미 당신을 위해 완료되었습니다!

속성

당신이 자바라고 "속성"을 사용할 수있는 메커니즘. 이것은 설명 된 것처럼 키 - 값 쌍을 포함하는 일반 텍스트 파일입니다. 일반적으로 확장자는 *.properties입니다.

일반 JDK의 일부이므로 Spring 또는 다른 프레임 워크를 사용할 필요가 없습니다. 따라서 프로젝트에 자유롭게 사용할 수 있습니다!

형식 안전해야하나요? 환경 설정을 사용하십시오!

타입 안전하려면 "환경 설정"을 대신 사용하십시오. 환경 설정 API는 일반 속성 API의 확장으로, 필요한 속성의 적절한 유형을 보장합니다.모두 함께 사용

문서

은 매우 간단합니다. 나는 문서를 반복합니다, 그래서이 두 자원을 확인하시기 바랍니다하지 않습니다 properties API, 당신은 기본 매개 변수 클래스 또는 인터페이스 같이 정의 할 수 있습니다 preferences API

+0

감사합니다.이 문제를 알지 못했습니다 ... – MattLBeck

+0

문제는 없습니다. 사람들은 환경 설정의 아름다움을 뛰어 넘는 속성 API 만 사용하는 경향이 있습니다. 그들은 모두 당신이 다루고있는 문제를 목표로 특별히 설계되었습니다. 그래서 그것을 사용하여 재미를보십시오 :) –

0

내가 언급 한 문제는 InPUT이라는 도구를 시작하고 유지하는 주된 이유 중 하나입니다. Preferences API는 간단한 예제에서 작동하지만 기본적으로 콘텐츠 유효성 검사, 값 범위 또는 비 프리미티브 유형 (문자열 제외)의 처리를 제공하지는 않습니다. 시뮬레이션이나 최적화를 다루는 경우에 계속 읽어 볼 수 있습니다.

이 같은 XML 디자인 공간 기술자에 매개 변수를 정의 할 수 있습니다 : (숫자)

<SParam id="simName" type="String"/> 
<NParam id="initialPopulationSize" type="integer" inclMin="10" inclMax="100"/> 
<NParam id="replacementRate" type="double" inclMin="0.3" inclMax="0.7"/> 

NParam 유형의 매개 변수, SParam (구조) 기본 매개 변수에 대한 의미를, 그것은 자바에 관해서.

는 는

귀하의 구성 (예를 들어, "config.xml에")는 이제 다음 값을 포함 할 수있다 : 당신이 할 모든 통화이다, 코드에서

<SValue id="simName" value="someName"/> 
<NValue id="initialPopulationSize" value="20"/> 
<NValue id="replacementRate" value="0.42"/> 

을 :

Design input = new Design("config.xml"); 
String simName = input.get("simName"); 
int initialPopulationSize = input.get("initialPopulationSize"); 
double replacementRate = input.get("replacementRate"); 

입력되었는지 확인합니다 매핑은 설명 자와 일치합니다. 일단 이것을 설정하면 코드를 건드리지 않고 자유 의지로 대안을 추가/제거하고 변경할 수 있습니다. 이를 사용하여 코드 매핑 설명자에 복잡한 중첩 클래스 (InPUT main page, Example 참조)를 주입하거나 매개 변수 설명자의 숫자 값 사이의 관계를 정의 할 수 있습니다 (엘리트 크기는 항상 채우기 크기보다 작음). 디자인 공간과 관련하여 (예를 들어, 최적의 매개 변수 설정을 찾기 위해) 무작위로 디자인을 생성 할 수도 있습니다. 이 툴을 다양한 프로그래밍 언어에 사용할 수있게함으로써 실험적 기술 어의 언어 불가지론 적 교환을 용이하게합니다 (C++이 제작 중입니다). 다양한 Java 예제는 이미 here에서 찾을 수 있습니다.