[GoF] Chain of Responsibility 패턴

패턴명칭

Chain of Responsibility

필요한 상황

어떤 기능을 구성하는 순차적인 처리들을 클래스별로 나눠 구현하여 수행할 수 있는 패턴이다.

예제 코드

URL을 구성하는 각 부분에 대한 처리를 수행하는 예제이다. 예를 들어http://127.0.0.1:8080과 같은 경우 URL을 구성하는 Protocol, Port, Address를 출력하는 기능을 각각 ProtocolParser, PortParser, AddressParser 클래스가 처리한다. 연속된 처리를 위해 Parser 클래스를 부모 클래스로 둔다. 먼저 부모 클래스인 Parser는 다음과 같다.

package pattern;

public abstract class Parser {
	protected Parser nextParser = null;

	public Parser setNext(Parser nextParser) {
		this.nextParser = nextParser;
		return this.nextParser;
	}
	
	public void run(String url) {
		process(url);
		if(nextParser != null) nextParser.run(url); 
	}
	
	protected abstract void process(String url);
}

URL 문자열에 대한 구체적인 처리는 process 추상 함수에서 수행한다. 먼저 Protocol을 처리하는 ProtocolParser 클래스는 다음과 같다.

package pattern;

public class ProtocolParser extends Parser {
	@Override
	public void process(String url) {
		int index = url.indexOf("://");
		if(index != -1) {
			System.out.println("PROTOCOL: " + url.substring(0, index));
		} else {
			System.out.println("NO PROTOCOL");
		}
	}
}

PortParser 클래스는 다음과 같다.

package pattern;

public class PortParser extends Parser {
	@Override
	public void process(String url) {
		int index = url.lastIndexOf(":");
		if(index != -1) {
			String strPort = url.substring(index+1);
			try {
				int port = Integer.parseInt(strPort);
				System.out.println("PORT: " + port);
				return;
			} catch(NumberFormatException e) {
				
			}
		}
		
		System.out.println("NO PORT");
	}
}

AddressParser 클래스는 다음과 같다.

package pattern;

public class AddressParser extends Parser {
	@Override
	public void process(String url) {
		int startIndex = url.indexOf("://");
		int lastIndex = url.lastIndexOf(":");
		
		if(startIndex == -1) {
			if(lastIndex == -1) {
				System.out.println("ADDRESS: " + url);
			} else {
				System.out.println("ADDRESS: " + url.substring(0, lastIndex));
			}
		} else if(startIndex != lastIndex) {
			System.out.println("ADDRESS: " + url.substring(startIndex+3, lastIndex));
		} else if(startIndex == lastIndex) {
			System.out.println("ADDRESS: " + url.substring(startIndex+3));
		} else {
			System.out.println("NO ADDRESS");
		}
	}
}

위의 클래스들을 사용하는 예제 코드는 다음과 같다.

package pattern;

public class Main {
	public static void main(String[] args) {
		Parser parser = new ProtocolParser();
		Parser parser1 = new PortParser();
		Parser parser2 = new AddressParser();
		
		parser.setNext(parser1).setNext(parser2);

		String url = "http://127.0.0.1:8080";
		System.out.println("INPUT: " + url);
		parser.run(url);
		
		url = "127.0.0.1:8080";
		System.out.println("\nINPUT: " + url);
		parser.run(url);
		
		url = "http://127.0.0.1";
		System.out.println("\nINPUT: " + url);
		parser.run(url);
		
		url = "127.0.0.1";
		System.out.println("\nINPUT: " + url);
		parser.run(url);
		
	}
}

출력 결과는 다음과 같다.

INPUT: http://127.0.0.1:8080
PROTOCOL: http
PORT: 8080
ADDRESS: 127.0.0.1

INPUT: 127.0.0.1:8080
NO PROTOCOL
PORT: 8080
ADDRESS: 127.0.0.1

INPUT: http://127.0.0.1
PROTOCOL: http
NO PORT
ADDRESS: 127.0.0.1

INPUT: 127.0.0.1
NO PROTOCOL
NO PORT
ADDRESS: 127.0.0.1
이 글은 소프트웨어 설계의 기반이 되는 GoF의 디자인패턴에 대한 강의자료입니다. 완전한 실습을 위해 이 글에서 소개하는 클래스 다이어그램과 예제 코드는 완전하게 실행되도록 제공되지만, 상대적으로 예제 코드와 관련된 설명이 함축적으로 제공되고 있습니다. 이 글에 대해 궁금한 점이 있으면 댓글을 통해 남겨주시기 바랍니다.

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다