Functional Programming in JAVA8이라는 책을 공부하면서 실무에서 사용할 수 있는 패턴을 응용하여 사용해봤습니다.
대부분의 프로젝트에서는 아이디, 패스워드 등 입력값에 대한 Validation Check를 해야하는데요. 사용자의 요청마다 매번 Pattern 객체를 생성하여 입력값에 대한 Validation Check를 하는 것은 비효율적이라 생각하게 되었습니다.
Pattern 객체를 생성하려면 많은 리소스가 필요하기 때문이죠.
프로그램이 실행 될 때 단 하나의 인스턴스만을 생성한 후 사용 시 가져온다면 매번 객체를 생성하기 위한 리소스가 들지 않기 때문에 프로그램의 효율이 증가되지 않을까 하고 다음 코드를 작성해보았습니다.
private Function<String, Pattern> pattern = regexp -> createAndCachePattern(regexp);
PatternStore() {
}
public Pattern getPattern(String regexp) {
return pattern.apply(regexp);
}
private synchronized Pattern createAndCachePattern(String regexp) {
class PatternFactory implements Function<String, Pattern> {
private final Map<String, Pattern> store = new ConcurrentHashMap<String, Pattern>();
@Override
public Pattern apply(String regexp) {
return store.computeIfAbsent(regexp, key->Pattern.compile(key));
}
}
if(!PatternFactory.class.isInstance(pattern)) {
pattern = new PatternFactory();
}
return pattern.apply(regexp);
}
1. JAVA8에서 제공하는 Function이라는 함수형 인터페이스를 이용하여 추상메소드가 실행하고자 하는 람다식을 정의합니다.
2. getPattern이라는 함수가 호출될 때 createAndCachePattern 함수가 호출됩니다.
3. createAndCachePattern 함수는 동기화(synchronized) 처리했기 때문에 한 시점에 하나의 스레드만이 사용할 수 있습니다.
4. if 조건문을 통해 해당 참조변수의 인스턴스가 PatternFactory가 아니라면 PatternFactory 인스턴스를 생성 후 할당합니다.
5. PatternFactory의 apply 함수를 호출하여 Pattern 객체를 반환합니다.
6. 두번째 getPattern 메소드 호출 시 PatternFactory의 apply 메소드를 호출하여 동기화로 인한 레이스 컨디션이 발생하지 않으며 한번 생성하였던 객체를 다시 사용할 수 있습니다.
출저 : Functional Programming in Java8