실례 설명 C\#의 직책 체인 모드

안녕하세요,후 씨 의 블 로그 에 오신 것 을 환영 합 니 다.오늘 우 리 는 디자인 모델 중의 직책 체인 모델 을 계속 이해 합 니 다.이것 은 비교적 간단 한 모델 입 니 다.여느 때 와 마찬가지 로 우 리 는 진실 한 세계 의 예 에 착안 하여 여러분 도 이 모델 의 응용 장면 에 대해 더욱 깊이 이해 할 수 있 습 니 다.
진짜 밤
직장 인 으로서 모두 가 휴가 를 내 는 것 이 낯 설 지 않다 고 믿 습 니 다.회사 마다 자신 이 휴가 를 내 는 절차 가 있 습 니 다.조금 더 신경 을 쓰 는 회 사 는 세밀 한 규정 도 있 습 니 다.예 를 들 어 3 일 이내 의 휴가 는 팀장 이 비준 할 권리 가 있 고 3 일 이상 의 휴가 는 더욱 높 은 등급 의 지도 자 를 찾 아 비준 해 야 합 니 다.이런 제 도 는 전형 적 인 권력 이 클 수록 직책 이 크다 는 것 이다.왜냐하면 연 휴 를 보 내 는 직책 은 고급 주관 에 게 만 존재 하기 때문이다.
이러한 세밀 한 요 구 를 규정 하 는 것 외 에 도 대부분의 회 사 는 소프트웨어 로 휴가 신청 절 차 를 실현 했다.휴가 신청 인원 이 휴가 신청 을 할 때 휴가 신청 일수 에 따라 권한 이 있 는 인원 에 게 심사 비준 을 전달 하고 이 시스템 의 코드 가 실현 되 는 지 살 펴 보 자.
휴가 신청 시스템 구현
이 시스템 에서 우 리 는 가정 한다.
4.567917.소조 장 은 3 일 이내 의 휴가 신청 을 승인 할 수 있다.
부서 장 은 5 일 이내 의 휴가 신청 을 심사 비준 할 수 있다.
4.567917.10 일 이내 의 휴가 신청 은 사장 만 이 심사 비준 할 수 있다.
4.567917.우 리 는 이 회사 의 경영 진 이 매우 인성 화 되 어 휴가 를 내 도 비준 을 받 을 수 있다 고 가정 합 니 다.10 일 이상 이 아니면 이런 상황 에서 비준 을 받 을 수 있 는 사람 이 없 기 때 문 입 니 다. 
휴가 신청
이것 은 가장 간단 한 유형 으로,휴가 일수 와 휴가 신청 인 을 봉인 하 였 다.

class VacationRequest
{
  public int DayNum { get; set; }
  public string RequesterName { get; set; }
}
방학 심사 비준 자
먼저 추상 적 인 유형 을 만 들 고 휴가 심사 비준 자,휴가 심사 비준 의 기본 논 리 를 봉인 한다.즉,현재 인원 이 현재 휴가 신청 을 심사 할 권한 이 있 으 면 처리 하 는 것 이다.

abstract class VacationApprover
{    
  protected VacationApprover(int dayCanHandle)
  {
    DayCanHandle = dayCanHandle;
  }

  public int DayCanHandle { get; protected set; }

  public void HandleVacationRequest(VacationRequest request)
  {
    if (request.DayNum <= DayCanHandle)
    {
      DoHandleVacationRequest(request);
    }
  }

  protected abstract void DoHandleVacationRequest(VacationRequest request);
}
물론 추상 류 는 알고리즘 골격 을 확정 하고 현재 인원 이 이 요 구 를 처리 할 수 있 을 때 만 심사 비준 작업 을 할 수 있 도록 제한해 야 한다.구체 적 인 심사 비준 실현 에 대해 서 는 하위 류 자신 에 게 덮어 씌 워 야 한다.이런 부모 류 의 고정 알고리즘 골격 에서 일부 커버 점 을 하위 류 에 노출 시 키 는 방법 은 바로 전에 우리 가 언급 한 Template Method 모델 이다.
구체 적 인 휴가 심사 비준 자
소조 장,부서 장,사장,모두 이곳 에서 창립 되 었 는데,그들 은 각각 3,5,10 일의 휴가 신청 을 심사 비준 할 수 있다.

class TeamLeader : VacationApprover
{
  private const int DAY_CAN_HANDLE_TEAMLEADER = 3;
  public TeamLeader() : base(DAY_CAN_HANDLE_TEAMLEADER) { }

  protected override void DoHandleVacationRequest(VacationRequest request)
  {
    Console.WriteLine("Now team leader handle this request");
    Console.WriteLine("Team leader accept this request");
  }
}

class DepartmentLeader : VacationApprover
{
  private const int DAY_CAN_HANDLE_DEPARTMENTLEADER = 5;
  public DepartmentLeader() : base(DAY_CAN_HANDLE_DEPARTMENTLEADER) { }

  protected override void DoHandleVacationRequest(VacationRequest request)
  {
    Console.WriteLine("Now department leader handle this request");
    Console.WriteLine("Department leader accept this request");
  }
}

class Boss : VacationApprover
{
  private const int DAY_CAN_HANDLE_BOSS = 10;
  public Boss() : base(DAY_CAN_HANDLE_BOSS) { }

  protected override void DoHandleVacationRequest(VacationRequest request)
  {
    Console.WriteLine("Now boss handle this request");
    Console.WriteLine("Boss accept this request");
  }
}
휴가 신청 승인 시스템
휴가 신청 시스템 은 통일 적 인 휴가 신청 인 터 페 이 스 를 제공 하고 내부 적 으로 휴가 신청 일 수 를 통 해 어느 심사 비준 자가 심사 비준 에 참여 하 는 지 결정 한다.

class VacationApproveSystem
{
  private VacationApprover teamLeader = new TeamLeader();
  private VacationApprover departmentLeader = new DepartmentLeader();
  private VacationApprover boss = new Boss();

  public void HandleVacationRequest(VacationRequest request)
  {
    Console.WriteLine("Now handle {0}'s {1} days' vacation request", request.RequesterName, request.DayNum);

    if (request.DayNum <= teamLeader.DayCanHandle)
    {
      teamLeader.HandleVacationRequest(request);
    }
    else if (request.DayNum <= departmentLeader.DayCanHandle)
    {
      departmentLeader.HandleVacationRequest(request);
    }
    else if (request.DayNum <= boss.DayCanHandle)
    {
      boss.HandleVacationRequest(request);
    }
    else
    {
      Console.WriteLine("Cannot handle this request after all");
    }
  }
}
테스트 코드

class Program
{
  static void Main(string[] args)
  {
    VacationApproveSystem system = new VacationApproveSystem();

    system.HandleVacationRequest(new VacationRequest() { DayNum = 5, RequesterName = "laohu" });

    system.HandleVacationRequest(new VacationRequest() { DayNum = 10, RequesterName = "laohu" });

    system.HandleVacationRequest(new VacationRequest() { DayNum = 12, RequesterName = "laohu" });
  }
}
결과 표시

모든 것 이 정상 적 인 것 이다.5 일 동안 부서 장 이 심사 비준 을 하고 10 일 동안 사장 이 심사 비준 을 하면 10 일 이상 아무 도 비준 할 수 없다.Good job。
뒤 를 돌아보다
1 판 코드 를 실현 한 후에 우 리 는 다시 고 개 를 돌려 보 았 다.비록 코드 기능 이 틀 리 지 않 았 지만 Vacation Approve System 은 너무 많은 직책 을 맡 은 것 같다.이 는 통 일 된 휴가 신청 승인 인 터 페 이 스 를 최종 사용자 에 게 제공 해 야 할 뿐만 아니 라 모든 휴가 신청 자 들 이 심사 비준 할 수 있 는 휴가 신청 일 수 를 알 고 내부 에서 휴가 신청 을 서로 다른 심사 자 에 게 전달 하 는 논 리 를 실현 해 야 한다.이렇게 하면 디 미트 의 법칙 을 위반 할 뿐만 아니 라 너무 많이 알 고 있 을 뿐만 아니 라 개폐 원칙 도 위반 할 수 있다.만약 에 어떤 심사 비준 자가 자신 이 심사 비준 할 수 있 는 휴가 일 수 를 수정 하면 이런 종류 가 파 급 될 것 이다.마지막 으로 단일 직책 인 한 가지 변 화 를 일 으 키 는 원인 만 있 을 수 있다.
이 를 감안 하여 우리 의 이 코드 는 단지 적합 한 것 이 라 고 할 수 있 을 뿐,구조 가 양호 하 다 고 말 할 수 는 없 으 니,성실 하 게 코드 를 재 구성 하 세 요.다음은 오늘 의 주인공 을 모 시 겠 습 니 다.
직책 체인 모드

구체 적 인 대상 과 요청 을 결합 하여 여러 대상 이 요청 을 처리 할 수 있 도록 합 니 다.대상 을 하나의 체인 으로 연결 하여 대상 이 처리 할 때 까지 체인 을 따라 요청 을 전달 합 니 다.
언뜻 들 으 니 좀 어색 하 다.
4.567917.구체 적 인 대상 과 요 구 를 결합 하 는 것―이 요 구 를 처리 할 대상 을 미리 지정 하지 마 세 요(모 를 때 가 많 기 때 문 입 니 다)4.567917.여러 대상 에 게 기 회 를 준다―한 명의 후보 대상 이 있 고 구체 적 으로 어떤 대상 을 사용 하 는 지 는 운행 할 때 결정 된다4.567917.연결 체인 전달 요구―링크 처럼 대상 에서 대상 간 의 체인 관 계 를 나타 내 고 다른 유형 을 통 해 if.else 의 방식 으로 실현 하지 말 아야 한다그래서 이렇게 보면 이 모델 은 우리 의 예 와 정말 잘 어울린다.우 리 는 이미 대부분의 일 을 했다.지금 남 은 것 은 심사 비준 자 를 수정 하여 심사 비준 자 를 연결 시 킬 수 있 도록 하 는 것 이다. 
코드 재 구성
휴가 신청 심사 비준 기 류 를 수정 하 다.
가장 중요 한 변경 은 기본 클래스 를 수정 하여 대상 을 연결 시 키 고 Vacation Approver 에 후계 노드 와 후계 노드 를 설정 하 는 방법 을 추가 하 는 것 이다.또한 기본 적 인 심사 비준 방법 에서 요청 전달 을 완성 한다.즉,휴가 신청 이 현재 심사 비준 자의 능력 범 위 를 초과 하면 후계 노드 로 전송 한다.수 정 된 종 류 는 다음 과 같다.

abstract class VacationApprover
{
  private VacationApprover nextVacationApprover = null;

  public void SetNextVacationApprover(VacationApprover approver)
  {
    nextVacationApprover = approver;
  }

  protected VacationApprover(int dayCanHandle)
  {
    DayCanHandle = dayCanHandle;
  }

  public int DayCanHandle { get; protected set; }

  public void HandleVacationRequest(VacationRequest request)
  {
    if (request.DayNum <= DayCanHandle)
    {
      DoHandleVacationRequest(request);
    }
    else
    {
      if(nextVacationApprover != null)
      {
        nextVacationApprover.HandleVacationRequest(request);
      }
      else
      {
        Console.WriteLine("Cannot handle this request after all");
      }
    }
  }

  protected abstract void DoHandleVacationRequest(VacationRequest request);
}
휴가 신청 심사 비준 시스템 을 수정 하 다.
기본 적 인 재 구성 이 끝 난 후에 휴가 심사 시스템 은 살 을 뺄 수 있 고 모든 판단 논 리 를 삭제 하 며 구조 함수 에서 만 체인 구성 작업 을 완성 한 다음 에 원 키 로 호출 하여 일치 하 게 할 수 있다.

class VacationApproveSystem
{
  private VacationApprover teamLeader = new TeamLeader();
  private VacationApprover departmentLeader = new DepartmentLeader();
  private VacationApprover boss = new Boss();

  public VacationApproveSystem()
  {
    teamLeader.SetNextVacationApprover(departmentLeader);
    departmentLeader.SetNextVacationApprover(boss);
  }

  public void HandleVacationRequest(VacationRequest request)
  {
    Console.WriteLine("Now handle {0}'s {1} days' vacation request", request.RequesterName, request.DayNum);

    teamLeader.HandleVacationRequest(request);
  }
}
테스트
다른 휴가 승인 서브 클래스 와 테스트 클 라 이언 트 는 변경 할 필요 가 없습니다.이번 재 구성 작업량 은 매우 적 고 코드 를 실행 하 며 모든 것 이 정상 적 이 며 재 구성 에 성공 하 였 습 니 다.
총결산
이것 이 바로 직책 체인 모델 의 사용 이다.상태 모드 와 비슷 해서 다음 과 같은 문 제 를 해결 했다.
4.567917.하위 클래스 를 추가 하여 일부 논리 적 판단 을 호출 클래스(Vaccation Approve System)에서 하위 클래스 로 옮 기 는 방식 으로 호출 클래스 를 디 미트 법칙 에 만족 시 킵 니 다4.567917.직책 체인 에 더 많은 노드 를 추가 하려 면 새로운 유형 과 체인 조립 부분의 코드 를 추가 하고 개폐 원칙 을 대체적으로 만족 시 켜 야 한다.(여 기 는 개폐 원칙 을 완전히 만족 시 킬 수 없다.수정 이 있 으 면 우 리 는 반드시 Vacation Approve System 류 를 바 꿀 것 이다.다만 우 리 는 코드 의 변 동량 이 적 도록 해 야 한다.코드 변동 제어 능력 향상)
상태 패턴 과 마찬가지 로 하위 폭발 위험 도 있다.
직책 체인 모델 과 상태 모델 이 그렇게 비슷 해 보 이 는 이상 어떤 차이 가 있 을 까?그것들의 차 이 는:
4.567917.상태 모델 중의 대상 은 상태 가 있 고 수시로 인 터 페 이 스 를 통 해 대상 의 현재 상 태 를 조회 할 수 있다.대상 은 바로 서로 다른 상태 가 있 기 때문에 서로 다른 행 위 를 나타 낸다.한편,직책 체인 모델 중의 대상 은 상태 가 없고 대상 과 체인 의 관 계 는 요청 과 처리 라인 의 관계 와 같다.인터페이스 가 없 으 면 현재 처리 라인 의 어느 노드 를 알려 줄 수 있 고 이렇게 할 의미 도 없다.우 리 는 요구 가 처리 되 었 는 지 에 만 관심 을 가진다4.567917.상태 모델 에서 의 상태 전환 은 무질서 할 수 있다.예 를 들 어 한 게임 캐릭터 가 그의 상태 가 허약 할 때 치 료 를 통 해 건강 으로 전환 할 수도 있 고 부상 을 통 해 빈사 로 전환 할 수도 있다.한편,직책 체인 에서 의 요청 전달 은 앞으로 의 길 밖 에 없다.어 렸 을 때 부터 팀장 에서 부서 장 까지 부서 장 에서 사장 까지.
상황 에 따라 적절 한 패턴 을 선택 하 는 것 이 올 바른 사용 방법 이다.이상 은 오늘 의 내용 입 니 다.여러분 이 좋아 하 시 기 를 바 랍 니 다.다음 에 뵙 겠 습 니 다!
이상 은 실례 를 들 어 C\#중의 직책 체인 모델 에 대한 상세 한 내용 입 니 다.C\#직책 체인 모델 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기