Hoon222y

[1226-4] 전략(Strategy) 패턴 / 탬플릿 메소드 패턴 본문

코딩/교육

[1226-4] 전략(Strategy) 패턴 / 탬플릿 메소드 패턴

hoon222y 2018. 12. 27. 23:15

전략(Strategy) 패턴 : 특정한 계열의 알고리즘들을 정의하고, 각 알고리즘을 캡슐화하며, 이 알고리즘들을 해당 계열 안에서 상호 교환 가능하게 만듬. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package Strategy;
 
import java.io.IOException;
// 현재 코드는 템플릿 메서드 패턴을 사용하는데 이는 상속을 사용하므로 
// 런타임에 정책을 변경할 수 없으며 데이터 공유도 안된다는 단점이 있음
// 이를 해결하기 위해 정책을 런타임에 변경할 수 있도록 인터페이스를 활용한 포함 관계로 구현.
public class Test {
    public static void main(String[] args) {
        LineEdit edit = new LineEdit();
        
        edit.setValidator(new Validator() {
            public boolean isValid(char ch) {return Character.isDigit(ch);}
        });
        
        while (true) {
            String text = null;
            try {
                text = edit.getText();
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(text);
        }
    }
}
// 정책을 런타임에 변경할 수 있도록 인터페이스를 도입합니다.
interface Validator {
    public boolean isValid(char ch);
}
class LineEdit {
    private StringBuffer text = new StringBuffer();
    private Validator validator = null;
    
    public void setValidator(Validator validator) {
        this.validator = validator;
    }
    
    public String getText() throws IOException{
        text.delete(0text.length());
        while(true) {
            char ch = (char)System.in.read();
            if (ch=='\n'break;
            if(validator == null || validator.isValid(ch))
                text.append(ch);
                }
        return text.toString();
    }
}
cs


탬플릿 메소드 패턴 : 알고리즘의 구조를 메서드에 정의하고 하위 클래스에서 알고리즘의 구조변경 없이 정책만 변경하는 패턴이다. 즉, 세부정책을 자식에게 위임하는 패턴이다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package TemplateMethod;
import java.io.IOException;
public class Test {
    public static void main(String[] args) {
     //모든 입력을 그대로 출력
     //LineEdit edit = new LineEdit();
 
     //숫자만 입력 받아 출력
     //DigitLineEdit edit = new DigitLineEdit();
 
     AlphabetLineEdit edit = new AlphabetLineEdit();
 
     while (true) {
        String text = null;
            try {
                text = edit.getText();
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(text);
        }
    //입력을 받아 출력하는 컴포넌트를 구현하되 유지 보수 및 객체지향적으로 구현해보아라
    }
}
class LineEdit{
    private StringBuffer text = new StringBuffer();
 
    public String getText() throws IOException {
     //문자열의 기존내용을 삭제한다.
     text.delete(0text.length());
     while(true) {
         char ch = (char)System.in.read();
         if(ch == '\n')
         break;
         text.append(ch);
     }
     return text.toString();
    }
}
 
class DigitLineEdit{
    private StringBuffer text = new StringBuffer();
 
    public String getText() throws IOException {
        text.delete(0text.length());
        while(true) {
            char ch = (char)System.in.read();
            if(ch == '\n')
                break;
            if(Character.isDigit(ch))
                text.append(ch);
            text.append(ch);
        }
        return text.toString();
     }
}
 
class AlphabetLineEdit{
     private StringBuffer text = new StringBuffer();
 
     public String getText() throws IOException {
         text.delete(0text.length());
         while(true) {
             char ch = (char)System.in.read();
             if(ch == '\n')
                 break;
             if(Character.isAlphabetic(ch))
                 text.append(ch);
        }
        return text.toString();
     }
}
cs
해당 코드의 경우 숫자와 영어를 섞어서 입력할 때 각 함수마다 각각에 해당되는 문자들을 출력해주는 class들이다. 하지만 이 때 비슷한 모양에 코드들이 너무 반복적으로 사용되는 단점이 있다. 이러한 코드의 중복을 해결할 수 있는 방법이 바로 탬플릿 메소드 패턴이다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.io.IOException;
public class Test {
    public static void main(String[] args) {
        //LineEdit edit = new LineEdit();
        //DigitLineEdit edit = new DigitLineEdit();
        AlphabetLineEdit edit = new AlphabetLineEdit();
        
        while (true) {
            String text = null;
            try {
                text = edit.getText();
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(text);
        }
    }
}
class LineEdit{
    private StringBuffer text = new StringBuffer();
    
    // 전체 알고리즘은 부모에게 두고 세부 정책은 자식에게 위임한다.
    protected boolean isValid(char ch) {return true;}
    
    public String getText() throws IOException {
        text.delete(0text.length());
        while(true) {
            char ch = (char)System.in.read();
            if(ch == '\n')
                break;
            if(isValid(ch))
                text.append(ch);
                }
        return text.toString();
    }
}
//이런 방식을 템플릿메소드 패턴이라고 한다.
class DigitLineEdit extends LineEdit{
    protected boolean isValid(char ch) {
        return Character.isDigit(ch);
    }
}
class AlphabetLineEdit extends LineEdit{
    protected boolean isValid(char ch) {
        return Character.isAlphabetic(ch);
    }
}
cs

메서드 호출 방법 

C++, C# : 함수 포인터, 가상함수(동적 바인딩)

JAVA : 메서드 오버라이딩(동적 바인딩)

Comments