자바 디자인 패턴: 체인 오브 리스폰시빌리티 패턴으로 요청 처리
자바 프로그램에서 요청 처리는 매우 중요한 작업이며, 이를 효율적으로 처리하기 위해서는 디자인 패턴을 사용할 필요가 있습니다. 디자인 패턴 중 체인 오브 리스폰시빌리티 패턴은 요청 처리를 순차적으로 처리할 수 있도록 구조화된 패턴입니다. 이번 글에서는 체인 오브 리스폰시빌리티 패턴의 구조와 원리, 그리고 자바 어플리케이션에서의 활용 방법과 예제를 살펴보겠습니다.
자바 디자인 패턴: 체인 오브 리스폰시빌리티 패턴 소개
체인 오브 리스폰시빌리티 패턴은 요청 처리를 순차적으로 처리하는 구조를 갖는 디자인 패턴입니다. 이 패턴은 요청 처리를 위한 객체들을 연결하여 체인 형태로 만들고, 각 객체가 요청을 처리할 수 있는지 여부를 판단하여 처리할 수 있으면 처리하고, 처리할 수 없으면 다음 객체로 요청을 전달하는 방식으로 동작합니다.
체인 오브 리스폰시빌리티 패턴은 요청 처리 시에 객체 간의 결합도를 낮추고, 객체의 역할을 분리하여 유연성을 높일 수 있습니다. 또한 새로운 요청 처리 객체를 추가하거나 기존 객체를 수정하여 요청 처리 방식을 변경하는 경우에도 코드 수정을 최소화할 수 있습니다.
체인 오브 리스폰시빌리티 패턴은 다음과 같은 구조로 이루어져 있습니다.

- Handler: 요청 처리를 담당하는 추상 클래스 또는 인터페이스. 실제 요청 처리 객체는 이 클래스를 상속하여 구현합니다.
- ConcreteHandler: 실제 요청 처리 객체. 요청을 처리할 수 있으면 처리하고, 처리할 수 없으면 다음 객체로 요청을 전달합니다.
- Client: 요청을 생성하고, 체인의 시작 객체를 생성합니다.
체인 오브 리스폰시빌리티 패턴의 구조와 원리
체인 오브 리스폰시빌리티 패턴은 요청 처리 객체를 연결하여 체인 형태로 만들고, 각 객체가 요청을 처리할 수 있는지 여부를 판단하여 처리할 수 있으면 처리하고, 처리할 수 없으면 다음 객체로 요청을 전달하는 방식으로 동작합니다.
요청 처리 객체를 연결하는 것은 다음과 같이 구현할 수 있습니다.
public abstract class Handler {
private Handler next;
public void setNext(Handler next) {
this.next = next;
}
public Handler getNext() {
return next;
}
public abstract void handleRequest(Request request);
}
public class ConcreteHandler1 extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE1) {
System.out.println("ConcreteHandler1 handles request: " + request.getName());
} else if (getNext() != null) {
getNext().handleRequest(request);
} else {
System.out.println("No handler found for request: " + request.getName());
}
}
}
public class ConcreteHandler2 extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE2) {
System.out.println("ConcreteHandler2 handles request: " + request.getName());
} else if (getNext() != null) {
getNext().handleRequest(request);
} else {
System.out.println("No handler found for request: " + request.getName());
}
}
}
public class Request {
private RequestType type;
private String name;
public Request(RequestType type, String name) {
this.type = type;
this.name = name;
}
public RequestType getType() {
return type;
}
public String getName() {
return name;
}
}
public enum RequestType {
TYPE1, TYPE2
}
public class Client {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
handler1.setNext(handler2);
Request request1 = new Request(RequestType.TYPE1, "Request 1");
Request request2 = new Request(RequestType.TYPE2, "Request 2");
handler1.handleRequest(request1);
handler1.handleRequest(request2);
}
}
위 코드는 체인 오브 리스폰시빌리티 패턴의 구조를 보여줍니다. Handler 클래스는 요청 처리를 담당하는 추상 클래스 또는 인터페이스로, ConcreteHandler 클래스는 실제 요청 처리 객체입니다. Client 클래스는 요청을 생성하고, 체인의 시작 객체를 생성합니다.
체인의 시작 객체인 handler1 객체는 ConcreteHandler1 객체를 다음 객체로 설정하고, ConcreteHandler1 객체는 ConcreteHandler2 객체를 다음 객체로 설정합니다. 이렇게 객체를 연결하면 요청이 전달될 때 체인 형태로 전달되며, 각 객체는 자신이 처리할 수 있는 요청인지 판단하여 처리할 수 있으면 처리하고, 처리할 수 없으면 다음 객체로 요청을 전달합니다.
자바 어플리케이션에서 체인 오브 리스폰시빌리티 패턴 활용
자바 어플리케이션에서 체인 오브 리스폰시빌리티 패턴은 요청 처리를 효율적으로 구현할 수 있는 방법입니다. 예를 들어, 웹 어플리케이션에서 요청을 처리하는 경우에는 체인 형태로 처리할 수 있습니다.
public abstract class Handler {
private Handler next;
public void setNext(Handler next) {
this.next = next;
}
public Handler getNext() {
return next;
}
public abstract void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
public class AuthenticationHandler extends Handler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (request.getUserPrincipal() == null) {
response.sendRedirect("/login");
} else if (getNext() != null) {
getNext().handleRequest(request, response);
}
}
}
public class AuthorizationHandler extends Handler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (request.isUserInRole("admin")) {
if (getNext() != null) {
getNext().handleRequest(request, response);
}
} else {
response.sendRedirect("/access-denied");
}
}
}
public class RequestHandler extends Handler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Handle the request
}
}
public class Application {
public static void main(String[] args) {
Handler authenticationHandler = new AuthenticationHandler();
Handler authorizationHandler = new AuthorizationHandler();
Handler requestHandler = new RequestHandler();
authenticationHandler.setNext(authorizationHandler);
authorizationHandler.setNext(requestHandler);
// Create a servlet filter that uses the Chain of Responsibility pattern
Filter chainFilter = new Filter() {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
authenticationHandler.handleRequest((HttpServletRequest) request, (HttpServletResponse) response);
}
};
}
}
위 코드는 웹 어플리케이션에서 체인 오브 리스폰시빌리티 패턴을 활용한 예제입니다. AuthenticationHandler는 인증 처리, AuthorizationHandler는 권한 처리, RequestHandler는 실제 요청 처리를 담당합니다. 이렇게 각 역할을 분리하고, 객체를 연결하여 체인 형태로 처리하면 요청 처리를 효율적으로 구현할 수 있습니다.
체인 오브 리스폰시빌리티 패턴을 활용한 요청 처리 예제
체인 오브 리스폰시빌리티 패턴을 활용하여 요청 처리를 구현하는 예제를 살펴보겠습니다.
public abstract class Handler {
private Handler next;
public void setNext(Handler next) {
this.next = next;
}
public Handler getNext() {
return next;
}
public abstract void handleRequest(Request request);
}
public class ConcreteHandler1 extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE1) {
System.out.println("ConcreteHandler1 handles request: " + request.getName());
} else if (getNext() != null) {
getNext().handleRequest(request);
} else {
System.out.println("No handler found for request: " + request.getName());
}
}
}
public class ConcreteHandler2 extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE2) {
System.out.println("ConcreteHandler2 handles request: " + request.getName());
} else if (getNext() != null) {
getNext().handleRequest(request);
} else {
System.out.println("No handler found for request: " + request.getName());
}
}
}
public class Request {
private RequestType type;
private String name;
public Request(RequestType type, String name) {
this.type = type;
this.name = name;
}
public RequestType getType() {
return type;
}
public String getName() {
return name;
}
}
public enum RequestType {
TYPE1, TYPE2
}
public class Client {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
handler1.setNext(handler2);
Request request1 = new Request(RequestType.TYPE1, "Request 1");
Request request2 = new Request(RequestType.TYPE2, "Request 2");
handler1.handleRequest(request1);
handler1.handleRequest(request2);
}
}
위 코드는 체인 오브 리스폰시빌리티 패턴을 활용하여 요청 처리를 구현한 예제입니다. ConcreteHandler1은 RequestType.TYPE1 요청을 처리하고, ConcreteHandler2는 RequestType.TYPE2 요청을 처리합니다. 이렇게 객체를 연결하면 요청이 전달될 때 체인 형태로 전달되며, 각 객체는 자신이 처리할 수 있는 요청인지 판단하여 처리할 수 있으면 처리하고, 처리할 수 없으면 다음 객체로 요청을 전달합니다.
위 예제를 실행하면 다음과 같은 결과가 출력됩니다.
ConcreteHandler1 handles request: Request 1
ConcreteHandler2 handles request: Request 2
결론
체인 오브 리스폰시빌리티 패턴은 요청 처리를 효율적으로 구현할 수 있는 디자인 패턴입니다. 객체 간의 결합도를 낮추고, 객체의 역할을 분리하여 유연성을 높일 수 있습니다. 또한 새로운 요청 처리 객체를 추가하거나 기존 객체를 수정하여 요청 처리 방식을 변경하는 경우에도 코드 수정을 최소화할 수 있습니다. 자바 어플리케이션에서 체인 오브 리스폰시빌리티 패턴을 활용하면 요청 처리를 효율적으로 구현할 수 있으며, 이를 위해 Handler, ConcreteHandler, Client 클래스를 구현하는 방법을 살펴보았습니다.
Post Views: 3