이 설계 패턴은 행동 설계 패턴으로 분류됩니다. 책임 사슬의 주된 목적은 느슨하게 결합하는 것인데, 예를 들어 송신자와 수신자 사이의 통신을 고려해보자, 송신자는 송신자가 누구인지 모르고 수신자는 발신자가 누구인지 알지 못한다. 이는 단순히 이 설계 패턴이 요청 유형에 따라 요청의 발신자와 수신자를 분리한다는 것을 의미합니다.
개발자가 연쇄 책임 패턴을 사용할 수 있는 상황입니까?
· 개발자가 요청의 송신자와 수신자를 분리하려는 경우
· 런타임에 결정되는 여러 개체가 요청을 처리할 수 있는 후보입니다.
· 개발자가 코드에서 처리기를 명시적으로 지정하지 않으려는 경우
· 수신기를 명시적으로 지정하지 않고 개발자가 여러 개체 중 하나에 요청을 실행하려는 경우.
위의 UML 다이어그램에서 볼 수 있듯이 이 설계 패턴에서는 핸들러라는 클래스를 사용하여 송신기와 수신기를 분리합니다.
예:
항공사가 비행 시간에 기초하여 항공기의 연료 수요를 계산하는 연료량 계획을 만드는 소프트웨어가 필요하다고 가정하자.
1단계: 처리기 추상 클래스를 구현합니다.
핸들러 클래스에서 후계자를 보유하는 참조 변수를 만들고 다음과 같은 추상 메서드를 만듭니다.
"최대 연료량 계산(연료량 계획 연료량 계획)"
package ChainOfResponsibilityExample;
public abstract class FuelQuantityHandler {
protected FuelQuantityHandler successor;
public void setSuccessor(FuelQuantityHandler successor) {
this.successor = successor;
}
public abstract float calculateMaxFuelQuantity (FuelQuantityPlan fuelQuantityPlan);
}
참고: 또한 이 클래스는 추상 클래스로 구현되지 않고 인터페이스 클래스로 만들 수 있습니다. 하지만 이 예에서는 추상적인 수업으로 구현했습니다.
2단계: 연료량 계획 클래스를 만들고 인스턴스(instance) 변수를 선언하며 적절한 생성자, 설정자 및 게터를 구현합니다.
package ChainOfResponsibilityExample;
public class FuelQuantityPlan {
private String flightPath;
private float flyingHours;
private float fuelQuantity;
public void setFuelQuantity(float fuelQuantity) {
this.fuelQuantity = fuelQuantity;
}
public FuelQuantityPlan(String flightPath, float flyingHours) {
this.flightPath = flightPath;
this.flyingHours = flyingHours;
}
public String getFlightPath() {
return flightPath;
}
public float getFlyingHours() {
return flyingHours;
}
public float getFuelQuantity() {
return fuelQuantity;
}
}
3단계: 수신기 클래스를 만들고 처리기 클래스를 부모 클래스로 만듭니다.
참고: 문서의 복잡성과 길이를 줄이기 위해 첫 번째 수신기 클래스와 마지막 수신기 클래스만 여기에 설명되어 있습니다.
package ChainOfResponsibilityExample;
public class ShortRange extends FuelQuantityHandler{
@Override
public float calculateMaxFuelQuantity(FuelQuantityPlan fuelQuantityPlan) {
fuelQuantityPlan.setFuelQuantity((float) (fuelQuantityPlan.getFlyingHours() * 0.2));
System.out.println("Short Range Fuel Quantity Added");
if ( fuelQuantityPlan.getFlyingHours() <= 5) {
return fuelQuantityPlan.getFuelQuantity();
} else {
return successor.calculateMaxFuelQuantity(fuelQuantityPlan);
}
}
}
package ChainOfResponsibilityExample;
public class IntercontinentalRange extends FuelQuantityHandler{
@Override
public float calculateMaxFuelQuantity(FuelQuantityPlan fuelQuantityPlan) {
fuelQuantityPlan.setFuelQuantity((float) (fuelQuantityPlan.getFuelQuantity() + (fuelQuantityPlan.getFlyingHours() - 12.5) * 0.8));
System.out.println("Intercontinental Range Fuel Quantity Added");
return fuelQuantityPlan.getFuelQuantity();
}
}
먼저 관련 값을 계산한 후, 해당 값이 다음 연료량 계산에 적합한지 확인한 후 연료량 계획 등급의 현재 인스턴스는 후속 인스턴스의 "calculateMaxFuelQuantity" 방법에 대한 인수로 통과된다.
리시버 등급에 해당하는 마지막 등급에서는 최종 연료량만 계산하고 연료량만 넘기면 됩니다.
4단계: 책임 설계 패턴의 연쇄를 시작할 초기 클래스를 만듭니다.
참고: 이것은 강제적인 단계가 아니며, 개발자는 첫 번째 수신기 클래스를 사용하여 책임 체인을 시작할 수 있습니다.
package ChainOfResponsibilityExample;
public class MinimumFuelQuantity extends FuelQuantityHandler{
@Override
public float calculateMaxFuelQuantity(FuelQuantityPlan fuelQuantityPlan) {
return successor.calculateMaxFuelQuantity(fuelQuantityPlan);
}
}
5단계: 주요 방법을 만들고 책임 연쇄 설계 패턴이 어떻게 작동하는지 확인합니다.
package ChainOfResponsibilityExample;
public class Application {
public static void main(String[] args) {
ShortRange shortRange = new ShortRange();
MidRange midRange = new MidRange();
LongRange longRange = new LongRange();
IntercontinentalRange intercontinentalRange = new IntercontinentalRange();
MinimumFuelQuantity minimumFuelQuantity = new MinimumFuelQuantity();
minimumFuelQuantity.setSuccessor(shortRange);
shortRange.setSuccessor(midRange);
midRange.setSuccessor(longRange);
longRange.setSuccessor(intercontinentalRange);
FuelQuantityPlan fuelQuantityPlan = new FuelQuantityPlan("AB1", 2.0f);
System.out.println(minimumFuelQuantity.calculateMaxFuelQuantity(fuelQuantityPlan));
FuelQuantityPlan fuelQuantityPlan1 = new FuelQuantityPlan("AB2", 6.0f);
System.out.println(minimumFuelQuantity.calculateMaxFuelQuantity(fuelQuantityPlan1));
FuelQuantityPlan fuelQuantityPlan2 = new FuelQuantityPlan("AB3", 8.0f);
System.out.println(minimumFuelQuantity.calculateMaxFuelQuantity(fuelQuantityPlan2));
FuelQuantityPlan fuelQuantityPlan3 = new FuelQuantityPlan("AB4", 14.0f);
System.out.println(minimumFuelQuantity.calculateMaxFuelQuantity(fuelQuantityPlan3));
}
}
이 클래스에서 초기 클래스를 포함한 모든 수신기 클래스 인스턴스를 선언하고 초기화합니다.
모든 수신기 클래스에 대한 후속 버전을 설정합니다.
책임 연쇄 설계 패턴의 장점:
· 개발자는 핵심 구현을 조작하지 않고 수신자와 송신자의 구조나 순서를 변경할 수 있다. 그 결과 객체 할당 업무의 유연성이 향상됩니다.
책임 연쇄 설계 패턴의 단점:
· 관련 수신기로 객체를 수신하는 것에 대해서는 보장되지 않습니다.
· 시스템의 성능이 영향을 받지만 코드 디버깅에서도 쉬운 작업이 아닙니다.
책임디자인 패턴의 사슬이 무엇인지, 책임의 사슬을 어떻게 구현할지, 언제 사용할지, 장단점이 무엇인지 이제 이해하셨으면 합니다.
'프로그래밍' 카테고리의 다른 글
Python을 사용하여 NFT 이미지 , 메타데이터 대량 생성 (0) | 2021.12.30 |
---|---|
당신의 넥스트JS 웹사이트를 2022년에 더욱 친근하게 만드세요. 자동 업데이트 사이트맵을 쉽게 추가할 수 있습니다. (0) | 2021.12.30 |
Google Foobar Challenge의 팁과 힌트 (0) | 2021.12.30 |
초보자를 위한 Neovim - 플러그인 관리 (0) | 2021.12.30 |
Fled 바코드 스캐너 만들기 (0) | 2021.12.30 |
댓글