JAVA/Design Pattern

스트래티지 패턴 (Strategy Pattern)

반응형

공통적인 특징을 가진 객체를 

만들 경우 우리는 대게 다음과 같이 

추상클래스나 인터페이스를 만들어 놓고, 그 것을 상속받아 객체를 구현한다.

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
// 추상 클래스
package com.wedul.study.strategy;
 
public abstract class Animals {
 
    public Animals() {}
 
    private String name;
    
    public Animals(String name) {
        this.name = name;
    }
 
    public void eat() {
     System.out.println("a gu a gu");
    }
    
    abstract void attck();
}
 
// 고양이
public class Cat extends Animals {
    public Cat() {}
 
    public Cat(String name) {
        super(name);
    }
 
    @Override
    void attck() {
        System.out.println("scretch and bite");
    }
 
}
 
// 강아지
public class Dog extends Animals {
    public Dog() {}    
 
    public Dog(String name) {
        super(name);
    }
 
    @Override
    void attck() {
        System.out.println("bark and bite");
    }
 
}
 
// main
public class Main {
    public static void main(String args[]) {
        Animals dog = new Dog();
        Animals cat = new Cat();
        
        dog.attck();
        cat.attck();
    }
}
 
 
// 결과
bark and bite
scretch and bite
cs



하지만 이런 유형의 경우 

몇가지 문제점이 발생할 수 있다.

문제점
1. 기존 추가된 객체의 동작을 변경하려는 경우.

강아지는 물지 않고, 고양이는 할퀴지 않는경우에 

기존의 코드를 수정을 해주어야 한다.

하지만 그런 경우 새로운 기능을 위해 기존의 속성을 변경해야 하기에 

OCP를 위반하는 행위이다.

2. 새로운 객체가 추가되었을 경우

새로운 rabbit이라는 객체가 추가되었을 때 고양이의 attack 메소드를 동일하게 사용하고 싶은 경우에도

별도로 만들어 주어야 한다.

이는 중복된 코드를 만드는 좋지 않은 코드 습관이 될 수 있다.

또한 attack의 의 성격이 변경될 경우 토끼와 고양이의 메소드를 모두 수정해 주어야 한다.

해결방법

이렇게 자주 변경되는 속성에 관해서는 

그 속성에 대한 인터페이스를 구분하는 것이 좋다.

위의 예제에서 보면 공격이라는 속성이 자주 변경 되는 경우

공격이라는 인터페이스를 만들고 

공격유형에 따른 객체를 인터페이스를 구현하여 만들고 동물에게 해당 속성을 부여해 주는 방식으로 진행해야 한다.


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
// 공격 타입 인터페이스
public interface AttactType {
    void attack();
}
 
// bite 타입
public class BiteAttackType implements AttactType {
 
    @Override
    public void attack() {
        System.out.println("bite you");
    }
 
}
 
// scretch 타입
public class ScretchType implements AttactType {
 
    @Override
    public void attack() {
        System.out.println("scretch use");
    }
 
}
 
// 공격 속성 부여
public abstract class Animals {
    private String name;
    private AttactType attactType;
    
    public Animals() {}
    
    public Animals(String name) {
        this.name = name;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public AttactType getAttactType() {
        return attactType;
    }
 
    public void setAttactType(AttactType attactType) {
        this.attactType = attactType;
    }
    
}
 
// main (동적으로 속성 부여)
public class Main {
    public static void main(String args[]) {
        Animals dog = new Dog();
        Animals cat = new Cat();
 
        // 속성 부여
        dog.setAttactType(new BiteAttackType());
        cat.setAttactType(new ScretchType());
        
        dog.getAttactType().attack();
        cat.getAttactType().attack();
    }
}
cs




위와 같이 스트래티지 패턴은 전략을 쉽게 바꿀 수 있도록 해주는 디자인 패턴이다.

스트래트지 패턴은 

역할에 따라 3가지 요소로 구분된다.

1) Strategy 
- 인터페이스나 추상화로 외부에서 동일한 방식으로 알고리즘을 호출하는 방법을 명시 ( 위의 예에서 Attack Type 인터페이스)
2) ConcreteStrategy
- 인터페이스를 구현한 실제 전략 객체들 (위의 예에서 bite Attack Type, Scretech Attack Type)
3) Context 
- 스트래티지 패턴을 이용하는 역할을 수행한다.  (위의 예에서 Animals)
- 위에서 생성된 전략을 setter을 통해서 매핑한다.



정리하면 

어떤 주체의 행위는 동일하나,
그 도구가 계속 변경된다면 그 도구를 인터페이스로 정의하고
인터페이스 메서드로 그 행위를 기재 한후.

주체에게 그 도구를 주입해서 동적으로 사용하는 방식을 고려하라.

반응형

'JAVA > Design Pattern' 카테고리의 다른 글

싱글톤 패턴 (Singleton Pattern)  (1) 2018.05.28
스테이트 패턴 (state pattern)  (0) 2018.05.28
커맨드 패턴 (command pattern)  (0) 2018.05.28
커맨드 패턴 (command pattern)  (0) 2018.05.27
옵저버 패턴 (Observer Pattern)  (0) 2018.05.27