記錄

Strategy pattern(스트래티지 패턴) 본문

IT_Fundamental/디자인 패턴

Strategy pattern(스트래티지 패턴)

surhommejk 2017. 11. 11. 11:02


strategy pattern(스트래티지 패턴)


여러 알고리즘을 하나의 추상적인 접근점(인터페이스)을 만들어

이 접근점에서 서로 교환가능하도록 하는 패턴

알고리즘을 정의하고 각각을 캡슐화하여 교환해서 사용가능 하도록 하는 패턴

출처: http://sycho-lego.tistory.com/6


---------------------------------------------------------------------------------------------------------------------

내가 원하던 것이 이런 것이었다. 디자인 패턴 공부를 시작하길 잘 했다는 생각이 든다. 계속 배워나가면 실력이 많이 늘 것 같다. 꾸준히 기록해 나갈 것이다. 처음으로 배운 것은 스트래티지 패턴이다. 게임 캐릭터가 무기를 바꾸는 예제로 공부했는데 무척 재미있었다. 내용이 아니고 원리가 재미있었다는 뜻이었다.

디자인 패턴 책도 빌리긴 했는데 입문용으로 더 적절해 보이는 강의가 있어서 인프런의 강의를 수강하고 있다. 이런 좋은 강의를 공짜로 들을 수 있다니 정말 좋은 세상이다.

(https://www.inflearn.com/course/%ec%9e%90%eb%b0%94-%eb%94%94%ec%9e%90%ec%9d%b8-%ed%8c%a8%ed%84%b4/)

그동안 인터페이스를 잘 쓸 일이 없었을 뿐더러(나는 그냥 '기능'을 공부해왔으니까) 어디에, 언제 쓰는지 잘 알지 못했는데 강의를 들으면서 '실무에서 어떤 식으로 쓰겠구나', '앞으로 내가 이렇게 써먹으면 좋겠구나'와 같은 이런 저런 생각이 들었다.



인터페이스 (선언과 구현이 분리, 통로, 위임)



인터페이스는

1. 선언과 구현이 분리

2. 통로

3. 위임

이 세 가지 개념을 잘 이해하고 있다면 앞으로의 활용도가 더 높아질 것이라 생각한다. 활용도가 높아진다는 말은 코드를 쓸데없이 길게 쓰지 않고 인터페이스를 활용해서 효과적인 코드를 작성해야 할 순간이 왔을 때 그 순간을 알아차리고 실제로 내가 구현할 수 있음을 의미한다.

아는 만큼 보인다고 했다. 이러한 것들을 모르고 그냥 인터페이스가 무엇인지만 아는 상태라면 내가 코드를 작성하면서 인터페이스를 효과적으로 활용할 수 있는 순간임에도 그것을 알아차리지 못할 것이라 생각한다.

위 도식도는 내가 수업을 들으며 예제를 구현한 것을 나타내고 있다. 아래는 내가 작성한 코드이다.


public interface Test_interface {
    
    //선언과 구현의 분리
    public void test_function(); //<--  여기서 바디를 입력하면
                                 //     컴파일이 되지 않는다
                                 //     인터페이스 내 함수는 바디X
                                 //     (오직 선언만)

} // class end

public class Test_class implements Test_interface {
    /* implements 하는 순간 클래스는 interface에 있는
    *    메소드를 Override해야 할 의무가 생긴다
    *    그래서, 구현하는 순간까지 에러가 표시된다
    */

    public void test_function() {

        System.out.println("A를 출력합니다");
        
    }

} // class end

public class Aobj {

    Test_interface test_interface;

    public Aobj() {

        test_interface = new Test_class();

    }

    public void deligate_function() {
        test_interface.test_function();
    }
    
} // class end

public class Main {

    public static void main(String[] args) {

        Test_interface go_through = new Test_class();
        /* <-- interface로 클래스를 담은 모습
         *   Test_class가 Test_interface를
         * implements하고 있기 때문에 가능하다
         * Test_class에서 implements부분을
         * 삭제하니 바로 에러가 뜬다
        */
        
        // 통로
        go_through.test_function();
        /*  go_through로 test_function을 Override하고 있는 Test_class를
           담았기 때문에 test_function의 call이 가능하다.
        */
        
        Aobj aobj = new Aobj();
        //  Aobj의 생성자에 Test_interface에 Test_class를 담도록 설정해두었음
        aobj.deligate_function();   
        /*  deligate_function에서 Test_interface를 이용해
            Test_class의 메소드를 call 하고 있다
        */
                
        GameCharacter JKyongsa = new GameCharacter();
        
        JKyongsa.attack();
        
        Sword sword = new Sword();
        JKyongsa.SetWeapon(sword); // 이렇게 만들어서 집어 넣는 것도 가능하고
        JKyongsa.attack();
        
        JKyongsa.SetWeapon(new Gun());// new Gun() 으로 바로 집어 넣는 것도 가능하다
        JKyongsa.attack();
                
        
    } // main end

} // class end


* 밑에 JKyongsa는 무기 예제 이므로 무시! 무기는 밑에 Animal 예제를 직접 만들어서 다시 구현하였다. Animal 클래스의 Setter를 통해서 원하는 동물 클래스 (Lion이나 Dog)를 Animal 클래스의 this.barking으로 call 하고 여기서 인터페이스를 이용해서 원하는 동물 클래스 (Lion이나 Dog)의 bark()를 사용하는 것이 가능하다. 




인터페이스 교환점을 통한 알고리즘(메소드)의 Call 및 교환

* Setter로 원하는 동물 클래스 (Lion이나 Dog)를 Animal클래스의 this.barking으로 설정하는 것이 가능한 이유는 Lion과 Dog가 Barking 인터페이스를 implements하고 있기 때문이다. Animal 클래스가 Barking 인터페이스를 implements하는 이유는 그냥 Bark()를 Override해서 무결한 코드를 짜기 위한 것이다.

사실 Animal은 Barking 인터페이스를 implements하지 않아도 실행 결과는 같다. 다만 implements하지 않아서 달라지는 것은 Animal이 정의하는 Bark()은 Lion이나 Dog가 Override하고 있는 공통적인 그 Bark()가 아니라 완전 새로운 Bark()인 것이다. 즉, 이름이 같을 뿐이지 완전 새로 정의된 Bark()인 것이다.


public interface Barking {

    public void Bark();
    
}

public class Lion implements Barking {

    public void Bark() {
        System.out.println("사자의 울음소리");
    }
    
}

public class Dog implements Barking {

    public void Bark() {
        System.out.println("개의 울음소리");
    }

}

public class Animal implements Barking{

    private Barking barking;

    public void SetBarking(Barking barking) {
        this.barking = barking;
    }

    public void Bark() {
        if (barking == null)
            System.out.println("지정된 동물이 없습니다");
        else
            barking.Bark();
    }

}

public class Main {

    public static void main(String[] args) {

        Animal UnknownAnimal = new Animal();

        UnknownAnimal.Bark();
        
        UnknownAnimal.SetBarking(new Lion());
        UnknownAnimal.Bark();

        UnknownAnimal.SetBarking(new Dog());
        UnknownAnimal.Bark();

    }

}


Comments