예전 에 쓴 Design Pattern 의 글 입 니 다.

Design Pattern Practice
1. 순서
본 고 는 간단 한 다 열 정렬 의 예 에서 착안 하여 Design Pattern (디자인 모델) 의 목적, 분석 과 실천 을 간단명료 하 게 설명 하고 자 한다.
글 의 예 는 Compositor Pattern 과 Proxy Pattern 을 사용한다.
이 동시에 문장의 예 도 문제 (조건 조합 문제) 의 해결 방안 을 제공 했다.
2. 문제 의 도입
Design Pattern (디자인 모델) 의 목 표 는 공통 문제 의 변 하지 않 는 부분 과 변화 부분 을 분리 하 는 것 이다.변 하지 않 는 부분 은 Design Pattern (디자인 모델) 을 구성한다.이 점 은 프레임 워 크 와 비슷 하 다.
다음은 정렬 의 예 를 들 어 문제 의 변 하지 않 는 부분 을 어떻게 추출 하 는 지 설명 한다.
자바 류 레코드 에 field 1, field 2, field 3 등 필드 가 있다 고 가정 합 니 다.

public class Record{
	public int field1;
	public long field2;
	public double filed3;
};

우 리 는 또 하나의 레코드 대상 의 배열 레코드 가 있다.우 리 는 이 배열 에 대해 서로 다른 조건 에 따라 정렬 해 야 한다.
우선, field 1 의 크기 에 따라 작은 것 부터 큰 것 까지 오름차 순 으로 정렬 합 니 다.
정렬 함 수 는 다음 과 같 습 니 다.

void sort(Record[] records){
	for(int i =….){
		for(int j=….){
			if(records[i].field1 > records[j].field1)
				// swap records[i] and records[j]
		}
	}
}

그 다음으로 field 2 의 크기 에 따라 작은 것 부터 큰 것 까지 오름차 순 서 를 매 긴 다.

void sort(Record[] records){
	for(int i =….){
		for(int j=….){
			if(records[i].field2 > records[j].field2)
				// swap records[i] and records[j]
		}
	}
}

또한, field 3 의 크기 에 따라 작은 것 부터 큰 것 까지 오름차 순 으로 정렬 합 니 다.
이런 요 구 는 너무 많아 서 우 리 는 중복 코드 를 너무 많이 썼 다.문제 의 변화 부분 은 조건 부분 (흑체 의 if 조건 판단 문) 만 판단 하 는 것 을 볼 수 있다.
우 리 는 Comparator 인 터 페 이 스 를 도입 하여 이 변화 하 는 부분 을 추출 할 수 있다.

public interface Comparator(){
	public boolean greaterThan(Record a, Record b);
};
sort        (         ):
void sort(Record[] records, Comparator compare){
	for(int i =….){
		for(int j=….){
			if(compare.greaterThen(records[i], records[j]))
				// swap records[i] and records[j]
		}
	}
}

이렇게 하면 첫 번 째 요구 에 대응 합 니 다. records 배열 은 field 1 의 크기 에 따라 정렬 합 니 다.
우 리 는 Comparator 인 터 페 이 스 를 실현 하 는 CompareByField 1 종 류 를 만 들 수 있다.

public class CompareByField1 implements Comparator{
public boolean greaterThan(Record a, Record b){
	if(a.filed1 > b.filed1){
		return ture;
	}
	return false;
}
}

sort 함수 호출: sort (records, new CompareByField 1 ();
이렇게 하면 첫 번 째 요구 에 대응 합 니 다. records 배열 은 field 2 의 크기 에 따라 정렬 합 니 다.
우 리 는 Comparator 인 터 페 이 스 를 실현 하 는 CompareByField 2 종 류 를 만 들 수 있다.

public class CompareByField2 implements Comparator{
public boolean greaterThan(Record a, Record b){
	if(a.filed2 > b.filed2){
		return ture;
	}
	return false;
}
}

sort 함수 호출: sort (records, new CompareByField 2 ();
C + + STL 의 명칭 에 따 르 면 이곳 의 sort 는 알고리즘 (Algorithm), records 는 용기 (집합), Comparator 는 함수 대상 (Function Object) 이 라 고 부른다.
JDK 의 java. util. collections 류 의 sort 방법 과 java. util. Comparator 인 터 페 이 스 는 이러한 사고방식 에 따라 설계 되 었 다.sort 와 Comparator 를 어떻게 활용 하여 다 열 정렬 문 제 를 해결 하 는 지 살 펴 보 자.
3. 다 열 정렬 문제
3.1 정렬 조건 의 수량
우 리 는 SQL 문 구 는 강력 한 정렬 기능 을 실현 할 수 있 고 서로 다른 필드 의 배열 에 따라 정렬 할 수 있 으 며 오름차, 내림차 순 으로 정렬 할 수 있다 는 것 을 알 고 있다.예 를 들 어 아래 의 문구.
order by field1 asc, field2 asc, field3 desc。
이 정렬 조건 은 field 1 의 오름차 순, field 2 의 오름차 순, field 3 의 내림차 순 으로 정렬 됩 니 다.
앞 에 있 는 필드 는 비교적 높 은 우선 순위 가 있 습 니 다.
예 를 들 어 두 개의 기록 A 와 B 는 다음 과 같은 조건 을 만족시킨다. (1) A. field 1 > B. field 1, (2) A. field 2 < B. field 2.
이때 order by field 1, field 2 문장 으로 정렬 하면 A > B.
상기 조건 중의 (1) A. field 1 > B. field 1 이 A. field 1 = = B. field 1 로 변 하면.이때 조건 (2) 이 작용 한다.이때, A < B.
자바 에서 이런 유연 하고 강력 한 순 서 를 어떻게 실현 하 는 지 살 펴 보 자.
우 리 는 여전히 상기 절의 기록 류 를 예 로 들 었 다.Record 류 는 세 개의 필드 가 있 습 니 다. 몇 가지 가능 한 정렬 조건 이 있 는 지 살 펴 보 겠 습 니 다.
(1) field 1 에 따라 정렬 합 니 다.(2) field 2 로 정렬 합 니 다.(3) field 3 에 따라 정렬 합 니 다.(4) field 1, field 2 로 정렬 합 니 다.(5) field 1 오름차 순 으로 field 2 내림차 순 으로 정렬...
각종 정렬 조건 의 배열 조합 은 대략 30 가지 가 있다.그리고 필드 개수 가 증가 함 에 따라 정렬 조건 의 개 수 는 멱급수 로 증가한다.
이전 절의 sort 와 Comparator 방법 에 따라 만약 에 우리 가 임의의 조건 에 따라 정렬 하 는 목적 을 달성 해 야 한다 면 우 리 는 모든 정렬 조건 에 Comparator 를 제공 해 야 한다. 우 리 는 30 개의 Comparator 류 가 필요 하 다.: -)
물론 우 리 는 이렇게 하지 않 을 것 이다. 우 리 는 이 문제 중의 똑 같은 중복 부분 을 계속 추출 하여 우리 의 해결 방안 을 최적화 시 킬 수 있다.
3.2 문제 분석
우 리 는 이 문제 에서 변화 하 는 부분 과 변 하지 않 는 부분 을 분석 할 것 이다.
위의 모든 정렬 조건 에서 변 하지 않 는 부분 은 3 부분 이 있 습 니 다. (1) A. field 1 과 B. field 1 의 비교, (2) A. field 2 와 B. field 2 의 비교, (3) A. field 3 와 B. field 3 의 비교;변화 하 는 부분 은 두 부분 이 있 는데 (1) 이 세 가지 비교 조건 의 임 의 조합 배열, (2) 오름차 와 내림차 가 있다.
이 분석 에 따 르 면 우 리 는 두 가지 유형, ReverseComparator 류 와 Composite Comparator 류 를 도입 했다.
Composite Comparator 클래스 는 필드 의 조합 배열 문 제 를 해결 하 는 데 사 용 됩 니 다.
ReverseComparator 클래스 는 필드 의 오름차, 내림차 문 제 를 해결 하 는 데 사 용 됩 니 다.
3.3 ReverseComparator 류 의 코드

import java.util.Comparator;

public class ReverseComparator implements Comparator{
  /** the original comparator*/
  private Comparator originalComparator = null;

  /** constructor takes a comparator as parameter */
  public ReverseComparator(Comparator comparator){
    originalComparator = comparator;
  }

  /** reverse the result of the original comparator */
  public int compare(Object o1, Object o2){
    return - originalComparator.compare(o1, o2);
  }
}

3.4 Composite Comparator 류 의 코드

import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;

public class CompositeComparator implements Comparator{
  /** in the condition list, comparators' priority decrease from head to tail */
  private List comparators = new LinkedList();

  /** get the comparators, you can manipulate it as need.*/
  public List getComparators(){
    return comparators;
  }

  /** add a batch of comparators to the condition list */
  public void addComparators(Comparator[] comparatorArray){
    if(comparatorArray == null){
      return;
    }

    for(int i = 0; i < comparatorArray.length; i++){
      comparators.add(comparatorArray[i]);
    }
  }

  /** compare by the priority */
  public int compare(Object o1, Object o2){
    for(Iterator iterator = comparators.iterator(); iterator.hasNext();){
      Comparator comparator = (Comparator)iterator.next();

      int result = comparator.compare(o1, o2);

      if(result != 0){
        return result;
      }
    }

    return 0;
  }
}

3.5 Comparator 의 조합 응용
이 절 은 위의 두 가지 용법 을 서술 한다.
앞의 정렬 문제 에 대응 하여 우 리 는 3 개의 Comparator 클래스 만 필요 합 니 다.
(1)Field1Comaprator;
(2)Field2Comaprator;
(3)Field3Comaprator。
이러한 Comparator 를 어떻게 조합 하여 서로 다른 정렬 조건 을 실현 하 는 지 예 를 들 어 설명 한다.
(1)order by field1, field2

 CompoiComparator myComparator = new CompoiComparator();
 myComparator. addComparators(
new Comparator[]{new Field1Comaprator (),  new Field2Comaprator ()};
);

// records is a list of Record
 Collections.sort(records,  myComparator);

(2)order by field1 desc, field2

 CompoiComparator myComparator = new CompoiComparator();
 myComparator. addComparators(
new Comparator[]{
new ReverseComparator(new Field1Comaprator ()),  
new Field2Comaprator ()};
);

// records is a list of Record
 Collections.sort(records,  myComparator);

여기 서 제공 하 는 ReverseComparator 류 와 Composite Comparator 류 는 모두 Decorator Pattern 을 사용 합 니 다.
Composite Comparator 류 는 Composite Pattern 이기 도 합 니 다.
4. 필터 조건 의 배열 조합
(shinwell 의 지적 에 감 사 드 립 니 다. 뒤의 코드 를 고 쳤 습 니 다)
여과 조건 문제 도 조건 조합 문제 의 범주 에 속한다.예 를 들 어 JDK 가 제공 하 는 java. io. File 류 는 파일 필터 방법 listFile (FileFilter) 을 제공 합 니 다. 사용 자 는 서로 다른 FileFilter 를 맞 춤 형 으로 설정 하여 서로 다른 필터 조건 을 실현 할 수 있 습 니 다. 예 를 들 어 파일 시간 이 특정한 범위 내 에 있 습 니 다.파일 접미사 이름, 파일 이름 이 특정한 패턴 에 부합 합 니 다.디 렉 터 리 인지 파일 인지 등등.
마찬가지 로 우 리 는 상기 해결 방법 을 응용 하여 유연 한 여과 조건 조합 을 실현 할 수 있다. 하나의 Composite Filter 류 의 임 의 조합 여과 조건 으로 하나의 ReverseFilter 류 를 배제 조건 으로 할 수 있다.
4.1 Composite Filter 류 의 코드

import java.io.FileFilter;
import java.io.File;

import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;

public class CompositeFilter implements FileFilter {

  /** in the filter list, every condition should be met. */
  private List filters = new LinkedList();

  /** get the filters, you can manipulate it as need.*/
  public List getFilters(){
    return filters;
  }

  /** add a batch of filters to the condition list */
  public void addFilters(FileFilter[] filterArray){
    if(filterArray == null){
      return;
    }

    for(int i = 0; i < filterArray.length; i++){
      filters.add(filterArray[i]);
    }
  }

  /** must meet all the filter condition */
  public boolean accept(File pathname) {
    for(Iterator iterator = filters.iterator(); iterator.hasNext();){
      FileFilter filter = (FileFilter)iterator.next();

      boolean result = filter.accept(pathname);

      // if any condition can not be met, return false.
      if(result == false){
        return false;
      }
    }

    // all conditions are met, return true.
    return true;
  }
}

4.2 ReverseFilter 클래스 의 코드

import java.io.FileFilter;
import java.io.File;

public class ReverseFilter implements FileFilter {
  /** the original filter*/
  private FileFilter originalFilter = null;

  /** constructor takes a filter as parameter */
  public ReverseFilter(FileFilter filter){
    originalFilter = filter;
  }

  /** must meet all the filter condition */
  public boolean accept(File pathname) {
      return !originalFilter.accept(pathname);
  }
}

5. 총화
본 고 는 Design Pattern 의 분석 과 실천 을 서술 하고 조건 조합 문제 의 해결 방향 을 논술 했다.
Enjoy it. :-)
Thanks.

좋은 웹페이지 즐겨찾기