본문 바로가기

Design Pattern

[Design Pattern] 전략 패턴(Strategy Pattern) - (2)

[Design Pattern] - [Design Pattern] 전략 패턴(Strategy Pattern) - (1)

 

전략 패턴(Strategy Pattern)실행 중에 알고리즘을 선택할 수 있게 하는 행위 소프트웨어 디자인 패턴이다.

 

객체들이 할 수 있는 행위 각각에 대하여 전략 클래스를 생성하고 유사한 행위들을 캡슐화하는 인터페이스를 정의하여 객체의 행위를 동적으로 바꾸고 싶은 경우 직접 행위를 수정하지 않고 전략을 교체하는 방법으로 행위를 유연하게 확장하는 패턴전략 패턴(Strategy Pattern)이라고 한다.

 

이미 전략 패턴에 대한 설명은 앞의 포스팅에 되어 있으므로 이번에는 예제만 간단히 살펴보도록 한다.

 

 

전략 패턴(Strategy Pattern) Diagram

 

 

 

 

1. Maven Dependency(pom.xml에 Library 추가)

  • pom.xml에 필요한 Library를 추가하여 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<!-- 
        MSWord페이지수전략.java
        MSPPT페이지수전략.java
 -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-scratchpad</artifactId>
    <version>4.0.1</version>
</dependency>
 
<!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox -->
<!-- 
        AAPDF페이지수전략.java
 -->
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.14</version>
</dependency>
Colored by Color Scripter
 

 

 

 

2. Strategy Interface(전략 인터페이스)

1
2
3
4
5
package com.acma.pattern.strategy;
 
public interface 페이지수전략 {
    int 페이지수();
}
Colored by Color Scripter
 

 

 

 

3. Concrete Class(구체 클래스, 전략 인터페이스를 구현한 클래스)

  • MSWord페이지수전략 클래스
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
package com.acma.pattern.strategy.impl;
 
import java.io.FileInputStream;
 
import org.apache.poi.hwpf.HWPFDocument;
 
import com.acma.pattern.strategy.페이지수전략;
 
import lombok.extern.slf4j.Slf4j;
 
@Slf4j
public class MSWord페이지수전략 implements 페이지수전략 {
    private HWPFDocument document;
    
    public MSWord페이지수전략(String path) {
        try {
            FileInputStream istream = new FileInputStream(path);
            this.document = new HWPFDocument(istream);
        } catch (Exception e) {
            log.debug("MSWord페이지수전략 catch Exception >>>> {}", e);
            e.printStackTrace();
        }
    }
    
    
    @Override
    public int 페이지수() {
        return document.getSummaryInformation().getPageCount();
    }
}
Colored by Color Scripter
 

 

  • MSPPT페이지수전략 클래스
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
package com.acma.pattern.strategy.impl;
 
 
import java.io.FileInputStream;
import java.io.IOException;
 
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
 
import com.acma.pattern.strategy.페이지수전략;
 
import lombok.extern.slf4j.Slf4j;
 
@Slf4j
public class MSPPT페이지수전략 implements 페이지수전략 {
    private HSLFSlideShow document;
    
    public MSPPT페이지수전략(String path) {
        try {
            this.document = new HSLFSlideShow(new FileInputStream(path));
        } catch (IOException e) {
            log.debug("MSPPT페이지수전략 catch Exception >>>> {}", e);
            e.printStackTrace();
        }
    }
    
    
    @Override
    public int 페이지수() {
        return document.getSlides().size();
    }
}
Colored by Color Scripter
 

 

  • AAPDF페이지수전략 클래스
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
package com.acma.pattern.strategy.impl;
 
import java.io.File;
import java.io.IOException;
 
import org.apache.pdfbox.pdmodel.PDDocument;
 
import com.acma.pattern.strategy.페이지수전략;
 
import lombok.extern.slf4j.Slf4j;
 
@Slf4j
public class AAPDF페이지수전략 implements 페이지수전략 {
    private PDDocument document;
    
    public AAPDF페이지수전략(String path) {
        try {
            this.document = PDDocument.load(new File(path));
        } catch (Exception e) {
            log.debug("AAPDF페이지수전략 catch Exception >>>> {}", e);
            e.printStackTrace();
        }
    }
    
    
    @Override
    public int 페이지수() {
        int pages = document.getNumberOfPages();
        try {
            document.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pages;
    }
}
Colored by Color Scripter
 

 

 

 

4. Context Class(컨텍스트 클래스)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.acma.pattern.context;
 
import com.acma.pattern.strategy.페이지수전략;
 
public class 문서컨텍스트 {
    private 페이지수전략 페이지수전략캡슐;
    
    public int 페이지수() {
        return 페이지수전략캡슐.페이지수();
    }
    
    public void set페이지수전략캡슐(페이지수전략 페이지수전략캡슐) {
        this.페이지수전략캡슐 = 페이지수전략캡슐;
    }
}
Colored by Color Scripter
 

 

 

 

5. Client(클라이언트)

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
package com.acma.pattern;
 
import org.junit.Test;
 
import com.acma.pattern.context.문서컨텍스트;
import com.acma.pattern.strategy.페이지수전략;
import com.acma.pattern.strategy.impl.AAPDF페이지수전략;
import com.acma.pattern.strategy.impl.MSPPT페이지수전략;
import com.acma.pattern.strategy.impl.MSWord페이지수전략;
 
import lombok.extern.slf4j.Slf4j;
 
@Slf4j
public class Client {
    
    페이지수전략 counter;
 
    @Test
    public void 전략패턴() {
        문서컨텍스트 msword = new 문서컨텍스트();
        counter = new MSWord페이지수전략("D:/PythonTistory/Secret/docDocument/aaa.doc");
        msword.set페이지수전략캡슐(counter);
        log.info("MSWord페이지수 >>>>>>>>> {}", msword.페이지수());
        
        
        문서컨텍스트 msppt = new 문서컨텍스트();
        counter = new MSPPT페이지수전략("D:/PythonTistory/Secret/docDocument/aaaa.ppt");
        msppt.set페이지수전략캡슐(counter);
        log.info("MSPPT페이지수 >>>>>>>>> {}", msppt.페이지수());
        
        
        문서컨텍스트 aapdf = new 문서컨텍스트();
        counter = new AAPDF페이지수전략("D:/PythonTistory/Secret/docDocument/aaaaa.pdf");
        aapdf.set페이지수전략캡슐(counter);
        log.info("AAPDF페이지수 >>>>>>>>> {}", aapdf.페이지수());
    }
}
Colored by Color Scripter
 

 

 

 

6. 실행 결과

실행 결과이다.

 

 

 


이제 확장을 해보자.

 

 

확장을 적용한 전략 패턴(Strategy Pattern) Diagram

 

 

 

 

1. Maven Dependency(pom.xml에 Library 추가)

1
2
3
4
5
6
7
8
9
10
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<!-- 
        MSXWord페이지수전략.java
        MSXPPT페이지수전략.java
 -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.0.1</version>
</dependency>
Colored by Color Scripter
 

 

 

 

 

3. Concrete Class(구체 클래스, 전략 인터페이스를 구현한 클래스)

  • MSXWord페이지수전략 클래스
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
package com.acma.pattern.strategy.impl;
 
import java.io.FileInputStream;
 
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
 
import com.acma.pattern.strategy.페이지수전략;
 
import lombok.extern.slf4j.Slf4j;
 
@Slf4j
public class MSXWord페이지수전략 implements 페이지수전략 {
    private XWPFDocument document;
    
    public MSXWord페이지수전략(String path) {
        try {
            FileInputStream istream = new FileInputStream(path);
            ZipSecureFile.setMinInflateRatio(0);
            this.document = new XWPFDocument(istream);
        } catch (Exception e) {
            log.debug("MSXWord페이지수전략 catch Exception >>>> {}", e);
            e.printStackTrace();
        }
    }
    
    
    @Override
    public int 페이지수() {
        return document.getProperties().getExtendedProperties().getUnderlyingProperties().getPages();
    }
}
Colored by Color Scripter
 

 

  • MSXPPT페이지수전략 클래스
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
package com.acma.pattern.strategy.impl;
 
import java.io.FileInputStream;
 
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
 
import com.acma.pattern.strategy.페이지수전략;
 
import lombok.extern.slf4j.Slf4j;
 
@Slf4j
public class MSXPPT페이지수전략 implements 페이지수전략 {
    private XMLSlideShow document;
    
    public MSXPPT페이지수전략(String path) {
        try {
            ZipSecureFile.setMinInflateRatio(0);
            document = new XMLSlideShow(new FileInputStream(path));
        } catch (Exception e) {
            log.debug("MSXPPT페이지수전략 catch Exception >>>> {}", e);
            e.printStackTrace();
        }
    }
    
    
    @Override
    public int 페이지수() {
        return document.getSlides().size();
    }
}
Colored by Color Scripter
 

 

 

 

 

5. Client(클라이언트)

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
package com.acma.pattern;
 
import org.junit.Test;
 
import com.acma.pattern.context.문서컨텍스트;
import com.acma.pattern.strategy.페이지수전략;
import com.acma.pattern.strategy.impl.AAPDF페이지수전략;
import com.acma.pattern.strategy.impl.MSPPT페이지수전략;
import com.acma.pattern.strategy.impl.MSWord페이지수전략;
import com.acma.pattern.strategy.impl.MSXPPT페이지수전략;
import com.acma.pattern.strategy.impl.MSXWord페이지수전략;
 
import lombok.extern.slf4j.Slf4j;
 
@Slf4j
public class Client {
    페이지수전략 counter;
    
    @Test
    public void 전략패턴() {
        문서컨텍스트 msword = new 문서컨텍스트();
        counter = new MSWord페이지수전략("D:/PythonTistory/Secret/docDocument/aaa.doc");
        msword.set페이지수전략캡슐(counter);
        log.info("MSWord페이지수 >>>>>>>>> {}", msword.페이지수());
        
        
        문서컨텍스트 msppt = new 문서컨텍스트();
        counter = new MSPPT페이지수전략("D:/PythonTistory/Secret/docDocument/aaaa.ppt");
        msppt.set페이지수전략캡슐(counter);
        log.info("MSPPT페이지수 >>>>>>>>> {}", msppt.페이지수());
        
        
        문서컨텍스트 aapdf = new 문서컨텍스트();
        counter = new AAPDF페이지수전략("D:/PythonTistory/Secret/docDocument/aaaaa.pdf");
        aapdf.set페이지수전략캡슐(counter);
        log.info("AAPDF페이지수 >>>>>>>>> {}", aapdf.페이지수());
        
        
        문서컨텍스트 msxword = new 문서컨텍스트();
        counter = new MSXWord페이지수전략("D:/PythonTistory/Secret/docDocument/bbb.docx");
        msxword.set페이지수전략캡슐(counter);
        log.info("MSXWord페이지수 >>>>>>>>> {}", msxword.페이지수());
        
        
        문서컨텍스트 msxppt = new 문서컨텍스트();
        counter = new MSXPPT페이지수전략("D:/PythonTistory/Secret/docDocument/bbb.pptx");
        msxppt.set페이지수전략캡슐(counter);
        log.info("MSXPPT페이지수 >>>>>>>>> {}", msxppt.페이지수());
    }
}
Colored by Color Scripter
 

 

 

 

 

6. 실행 결과

실행 결과이다.

 

MS Word의 "docx" 확장자와 MS Powerpoint의 "pptx" 확장자를 갖는 문서의 페이지수를 구하기 위해서 소스를 수정하지 않고 페이지수전략(Strategy Interface)를 implement한 MSXWord페이지수전략 클래스와 MSXPPT페이지수전략 클래스를 추가하는 것만으로 값을 구할 수 있음을 확인할 수 있다.

이처럼 전략 패턴을 사용하면 직접 행위를 수정하지 않고 전략을 교체하는 방법으로 행위를 유연하게 확장할 수 있다.

 

전략패턴다이어그램-2.pptx
0.06MB
strategyPattern_2.zip
0.07MB

 

 

 

# 디자인 패턴은 객체지향적으로 발생하는 여러가지 문제를 푸는 방법을 모아놓은 것이다. 정답이라기보다는 예제 모음이며 상황을 이해하고 적절하게 적용하는 방법을 배워야 한다는 보스의 말씀... 잊지 말자...