Hyeonuk_.log

토비의 스프링 읽다가 템플릿/콜백 기록 본문

Dev_.log/Spring

토비의 스프링 읽다가 템플릿/콜백 기록

Hyeonuk_. 2022. 3. 6. 21:48

토비의 스프링 3장을 읽다가 템플릿/콜백 연습 기록, 아래의 내용은 모두 토비의 스프링 참고하였습니다.

public class CalcSumTest {

	@Test
	public void sumOfNumber() throws IOException {
		Calculator cal = new Calculator();
		int sum = cal.calcSum(getClass().getResource("numbers.txt").getPath());
		assertThat(sum, is(10));
	}
}

테스트코드 작성 후 실제 구현 코드 작성

public class Calculator {

	public Integer calcSum(String filepath) throws IOException {
		BufferedReader bufferedReader = null;
		
		try {
			bufferedReader = new BufferedReader(new FileReader(filepath));
			Integer sum = 0;
			String line = null;
			while((line = bufferedReader.readLine()) != null) {
				sum += Integer.parseInt(line);
			}
			return sum;
		} catch (IOException e) {
			System.out.println(e.getMessage());
			throw e;
		} finally {
			if(bufferedReader != null) try {bufferedReader.close();} catch(IOException e) {};
		}
	}
}

템플릿/콜백을 적용할 때는 템플릿과 콜백의 경계를 정하고 템플릿이 콜백에게, 콜백이 템플릿에게 각각 전달하는 내용이 무엇인지 파악하는게 가장 중요하다. 

곱셈을 만들건 나눗셈을 만들건 변하는 부분은 아래의 부분이다.

Integer sum = 0;
String line = null;
while((line = bufferedReader.readLine()) != null) {
	sum += Integer.parseInt(line);
}
return sum;

 

이를 기반으로 리팩토링 해보자

공통 부분을 뽑아낼 인터페이스 정의

public interface LineCallback {
	public Integer doSomethingWithLine(String line, Integer value);
}

기존 클래스를 템플릿/콜백으로 리팩토링

public class Calculator {

	public Integer calcSum(String filepath) throws IOException {
		LineCallback sumCallback = new LineCallback() {

			@Override
			public Integer doSomethingWithLine(String line, Integer value) {
				return value + Integer.valueOf(line);
			}
			
		};
		
		return lineReadTemplate(filepath, sumCallback, 0);
	}
	
	public Integer calcMultiply(String filepath) throws IOException {
		LineCallback multiplyCallback = new LineCallback() {

			@Override
			public Integer doSomethingWithLine(String line, Integer value) {
				return value * Integer.valueOf(line);
			}
			
		};
		
		return lineReadTemplate(filepath, multiplyCallback, 1);
	}

	public Integer lineReadTemplate(String filepath, LineCallback callback, int i) throws IOException {
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(filepath));
			Integer resInteger = i;
			String line = null;
			while((line = br.readLine()) != null) {
				resInteger = callback.doSomethingWithLine(line, resInteger);
			}
		} catch (IOException e) {
			System.out.println(e.getMessage());
			throw e;
		} finally {
			if(br != null) { try { br.close(); } catch (IOException e) {} };
		}
		return null;
	}
}

 

만약 여기서 결과의 타입을 다양하게 가져다려면????

제네릭을 이용!!!

public interface LineCallback<T> {
	public T doSomethingWithLine(String line, T value);
}
public class Calculator {

	public Integer calcSum(String filepath) throws IOException {
		LineCallback<Integer> sumCallback = new LineCallback<Integer>() {

			@Override
			public Integer doSomethingWithLine(String line, Integer value) {
				return value + Integer.valueOf(line);
			}
			
		};
		
		return lineReadTemplate(filepath, sumCallback, 0);
	}
	
	public Integer calcMultiply(String filepath) throws IOException {
		LineCallback<Integer> multiplyCallback = new LineCallback<Integer>() {

			@Override
			public Integer doSomethingWithLine(String line, Integer value) {
				return value * Integer.valueOf(line);
			}
			
		};
		
		return lineReadTemplate(filepath, multiplyCallback, 1);
	}

	public <T> T lineReadTemplate(String filepath, LineCallback<T> callback, T i) throws IOException {
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(filepath));
			T resInteger = i;
			String line = null;
			while((line = br.readLine()) != null) {
				resInteger = callback.doSomethingWithLine(line, resInteger);
			}
		} catch (IOException e) {
			System.out.println(e.getMessage());
			throw e;
		} finally {
			if(br != null) { try { br.close(); } catch (IOException e) {} };
		}
		return null;
	}
}
Comments