2가지 방식을 정리해본다.
- enum이 클래스의 생성자를 갖고 있는 방식.
package com.example.demo.enumTest.type;
import com.example.demo.enumTest.connector.*;
import java.util.function.Supplier;
public enum ConnectionType {
FTP(FTPConnector::new),
HTTP(HttpConnector::new),
SUPERMAN(SuperManConnector::new),
NEW(NewConnector::new);
ConnectionType(Supplier<BaseConnector> instantiator){
this.instantiator= instantiator;
}
Supplier<BaseConnector> instantiator;
public BaseConnector newInstance(){
return this.instantiator.get();
}
}
enum으로 현재 프로젝트가 지원하는 Connecting 방식을 정의하고,
각 방식별로 BaseConnector의 생성자를 갖게하여
newInstance()를 호출해 사용하는 방식이다.
//Info info 는 connectionType을 멤버변수로 갖고 있는 객체.
BaseConnector connector = info.getConnectionType().newInstance();
사용하는 곳에서는 그저 connectionType.newInstance()를 호출하여 새로운 커넥터를 생성하면 된다.
위 방식은 Class가 no argument constructor를 갖고 있어야 오류가 나지 않는다.
만일 인자를 필요로 하는 constructor만 갖고있다면
Supplier<T>
Function<T,Q>
BiFunction<T,Q,R>
중에 알맞는 걸 사용하도록 하자.
만일 그 이상이거나 생성자의 인자로 generic 을 받는다면,
아래와 같이 enum을 구성해도 된다.
- Class를 갖고있는 방식
package com.example.demo.enumTest.type;
import com.example.demo.enumTest.file_formatter.BaseFormatter;
import com.example.demo.enumTest.file_formatter.SimpleKeyValue;
import com.example.demo.enumTest.file_formatter.XmlFormatter;
import org.w3c.dom.Document;
import java.lang.reflect.InvocationTargetException;
public enum FileType {
SIMPLE_KEY_VALUE(SimpleKeyValue.class, String.class),
XML(XmlFormatter.class, Document.class);
FileType(Class<? extends BaseFormatter<?>> formatClass,Class<?> rawDataClass){
this.formatClass = formatClass;
this.rawDataClass = rawDataClass;
}
Class<? extends BaseFormatter<?>> formatClass;
Class<?> rawDataClass;
public BaseFormatter<?> newInstance(Object rawData, String rule){
try {
return this.formatClass.getConstructor(this.rawDataClass,String.class).newInstance(rawData,rule);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
}
이 방식은 reflection을 이용해 newInstance를 만든다.
생성할 클래스 (formatClass), generic 인자 클래스(rawDataClass) 를 인자로 갖는 형태이다.
사용할때는 위와 똑같이 사용하면 된다.
//info 는 FileType을 멤버변수로 갖고있는 객체
//rawData와 rule은 적당한 객체.
BaseFormatter<?> formatter = info.getFileType().newInstance(rawData,rule);