ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바 nextstep - 인터페이스, 전략패턴
    카테고리 없음 2023. 7. 25. 16:59

    1. 인터페이스란? (사전적의미)

     

    - 하나의 시스템을 구성하는 2개의 구성요소(하드웨어,소프트웨어) 또는 2개의 시스템이 

        상호 작용할 수 있도록 접속되는 경계

    - 이 경계에서 상호 접속하기 위한 조건, 규약 등을 포괄적으로 가리키는말 

     

    2. 인터페이스 예시 

     

     JDBC를 통해 이해해보기

    -> DB를 교체해야할 때 만약 DB를 담당하는 코드와 자바코드가 밀접하게 연결되어 있다면,

        DB를 교체해야할 때 많은 비용과 시간이 발생할 것이다 (전부 수정)

    -> 이를 위한 해결방법으로 인터페이스를 사용한다

         JDBC(DB연결/인증, SQL쿼리생성/문장실행, 결과패치) 인터페이스 [규약,표준 생성]

          -> Mysql,oracle 등이 이에 맞게 구현체 만듦

          -> DB작업을 할 때 이제 JDBC에서 제공하는 API만을 사용함 (내부 구현은 각 DB별로 따로 되어 있다)

     

    3. 자바에서 interface란 

     

    - 서비스 집중화 보단, 분리와 다형성에 더 초점이 맞춰진다.

    - 인터페이스는 더 높은 추상화를 위해 사용된다.

    - 구현 로직은 존재하지 않으며, 메소드에 대한 입력과 출력만 정의한다.

    - 인터페이스를 통해 추상화를 하는 이유는 소프트웨어 변경이 발생할 경우 소스 코드 변경을 최소화하여 

       유지보수 비용을 줄이고, 변화에 빠르게 대응하기 위함이다.

    - 단 추상화를 위해 개발 비용이 증가한다.

     

    4. 인터페이스 활용 예시

     

    -  인터페이스를 만들 때는 특정 부품을 떠올려보자. 

    -  부품을 만들 수 있는 틀만을 제공하고, 세부 내용은 필요에 따라 구현하도록 분리한다고 생각하자

    -  특정 부분들을 집중화보단 도구화한다고 생각해보자.

    - 이러한 인터페이스는 하나의 캡슐, 일부 기능, 코드의 일부 구간 3가지 패턴에서 마감 기능을 할 수 있다.

     

    4.1 캡슐 

     

    - 필요에 따라 클래스를 교체해서 사용해야할 때 인터페이스를 사용하면, 내부 구현 클래스가 뭔지는 상관없이 

       참조변수 B에 담아서 사용하면 된다.

    - main메서드에서 B1혹은 B2이 필요하다고 해보자

    - B1, B2를 그냥 생성할 수도 있지만, B라는 인터페이스를 통해서 생성할 수도 있다.

    - 이때 소스코드에는 변화를 주지 않고 변경하는 방법은 아래와 같다.

    public static void main(String[] args) throws Exception{
            InputStream is = Main.class.getResourceAsStream("newinstance.txt");
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            Class bclazz = Class.forName(br.readLine());
            B b = (B)bclazz.newInstance();
            b.printHowis();
        }
    public interface B {
        void printHowis();
    }
    
    public class B1 implements B{
        @Override
        public void printHowis() {
            System.out.println("this is B1");
        }
    }
    
    public class B2 implements B{
        @Override
        public void printHowis() {
            System.out.println("This is B2");
        }
    }
    //newinstance.txt
    
    interfaces.B2

     

    4.2 일부 기능 

     

    private static int sumFunc(sumFunction f,List<Integer> list){
            return f.listsum(list);
        }
        
     //list를 더하는 기능을 인터페이스를 통해서 구현하도록 만들었다.
     public static void main(String[] args) throws Exception{
            List<Integer> list = List.of(1,2,3,4,5,6,7,8,9,10);
    
            sumFunction f1 = (list1) ->{
                int result =0;
                for(int i : list1){
                    result +=i;
                }
                return result;
            };
    
            sumFunction f2 = new sumFunction() {
                @Override
                public int listsum(List<Integer> list) {
                    int result=0;
                    for(int i : list){
                        result += i*2;
                    }
                    return result;
                }
            };
            System.out.println(sumFunc(f1,list));
            System.out.println(sumFunc(f2,list));
    
        }

    어떤 인터페이스를 집어넣느냐에 따라 결과가 다를 것이다.

     

    4.3 코드 일부 구간 

     

    move를 처리하는 조건문을 인터페이스로 처리하였다.

    public void move(MoveStretergy moveStretergy){
            if(moveStretergy.moveable())
                pos =pos.move();
        }
    public class RadomMoving implements MoveStretergy{
        private static final int MAX_BOUND =10;
        private static final int MOVABLE =4;
    
        @Override
        public boolean moveable() {
            return getRadomNum() >= MOVABLE;
        }
    
        private int getRadomNum() {
            return new Random().nextInt(MAX_BOUND);
        }
    }

    어떤 구현 클래스를 매개변수로 전달하느냐에 따라 조건문의 결과가 바뀔 것이고

    각 구현 클래스는 요구사항에 맞게 자유롭게 오버라이딩 하면 된다.

     

    5.  전략패턴(Stratey Pattern)

     

    - 알고리즘 패밀리를 정의, 각 패밀리를 별도의 클래스에 넣은 후 객체들이 상호교환 하도록 하는 행동 디자인 패턴 

    - 실행 중 알고리즘 전략을 선택하여 객체 동작을 실시간으로 바뀌도록 한다.

    - 전략 패턴이란 객체들이 할 수 있는 행위 가각에 대해 전략 클래스를 생성

    - 유사한 행위들을 캡슐화 하는 인터페이스 정의

    - 객체 행위를 동적으로 바꾸고 싶지 않을 경우 직접 행위를 수정하지 않고, 전략만 바쭘

    - 행위를 유연하게 확장하는 것을 의미한다.

     

     

    5.1 전략 패턴의 구조 

     

    출처: https://refactoring.guru/ko/design-patterns/strategy

    1. context : 특정 알고리즘을 실행해야할 때 해당 알고리즘과 연결된 전략 객체의 메서드 호출 

    2. 전략 인터페이스: 모든 전략 구현체에 대한 공용 인터페이스 

    3.전략 알고리즘 객체들: 알고리즘 행위, 동작을 객체로 정의한 구현체 

    4. 클라이언트: 특정 전략 객체를 컨텍스트에 전달하여 전략을 등록한다.

     

    //전략 알고리즘 
    interface IStrategy {
        void doSomething();
    }
    
    // 전략 알고리즘 구현체 
    class ConcreteStratey1 implements IStrategy {
        public void doSomething() {}
    }
    
    // 전략 알고리즘 구현체 
    class ConcreteStratey2 implements IStrategy {
        public void doSomething() {}
    }
    // 컨텍스트(전략 등록/실행)
    class Context {
        IStrategy Strategy; // 전략 인터페이스를 합성(composition)
    	
        // 전략 교체 메소드
        void setStrategy(IStrategy Strategy) {
            this.Strategy = Strategy;
        }
    	
        // 전략 실행 메소드
        void doSomething() {
            this.Strategy.doSomething();
        }
    }
    // 클라이언트(전략 교체/전략 실행한 결과를 얻음)
    class Client {
        public static void main(String[] args) {
            // 1. 컨텍스트 생성
            Context c = new Context();
    
            // 2. 전략 설정
            c.setStrategy(new ConcreteStrateyA());
    
            // 3. 전략 실행
            c.doSomething();
    
            // 4. 다른 전략 설정
            c.setStrategy(new ConcreteStrateyB());
    
            // 5. 다른 전략 시행
            c.doSomething();
        }
    }

     

    5.2 예시 1

    출처:https://victorydntmd.tistory.com/292

    - 위와 같이 Train과 Bus 클래스가 있고, 두 클래스가 Movable인터페이스를 구현했다고 가정

    - 이 두 클래스를 사용하는 Client도 있다

     

    public interface Movable{
    	public void move();
    }
    
    public class Train implements Movable{
        public void move(){
            System.out.println("선로를 통해 이동");
        }
    }
    public class Bus implements Movable{
        public void move(){
            System.out.println("도로를 통해 이동");
        }
    }
    
    public class Client {
        public static void main(String args[]){
            Movable train = new Train();
            Movable bus = new Bus();
    
            train.move();
            bus.move();
        }
    }

     - 추후에 Bus가 움직이는 방식이 바뀐다면, Bus에 move메서드를 직접 수정해야한다.

    - 이는 SOLID원칙 중 OCP에 위배된다. 기존의 move()를 수정하지 않으면서 행위를 수정할 수 있는 

       방법을 찾아야 한다. 

    - 혹은 추후에 택시, 자가용, 고속버스가 버스의 move()와 동일하게 변경되었다면, 모든 move()를 수정해야하는 

       번거로움이 발생한다(동일 메서드 중복)

     

    5.2.2

     

    1. move에 대한 전략 인터페이스 생성 -> 각 전략에 맞게 이를 구현한 구현체 생성 

    출처:https://victorydntmd.tistory.com/292

    public interface MovableStrategy {
        public void move();
    }
    public class RailLoadStrategy implements MovableStrategy{
        public void move(){
            System.out.println("선로를 통해 이동");
        }
    }
    public class LoadStrategy implements MovableStrategy{
        public void move() {
            System.out.println("도로를 통해 이동");
        }
    }

    2. 각 운송수단에 해당하는 클래스는 위 movableStrategy 구현 클래스를 주입 받아 move메서드를 

        사용할 수 있도록 변경 

     

    출처: https://victorydntmd.tistory.com/292

    public class Moving //컨텍스트 {
        private MovableStrategy movableStrategy;
    
        public void move(){
            movableStrategy.move();
        }
    
        public void setMovableStrategy(MovableStrategy movableStrategy){
            this.movableStrategy = movableStrategy;
        }
    }
    public class Bus extends Moving{
    
    }
    public class Train extends Moving{
    
    }

    3. 운송수단을 사용하는 클라이언트에서 각 운송 수단에 맞는 전략을 주입 

     

    public class Client {
        public static void main(String args[]){
            Moving train = new Train();
            Moving bus = new Bus();
    
            /*
                기존의 기차와 버스의 이동 방식
                1) 기차 - 선로
                2) 버스 - 도로
             */
            train.setMovableStrategy(new RailLoadStrategy());
            bus.setMovableStrategy(new LoadStrategy());
    
            train.move();
            bus.move();
    
            /*
                선로를 따라 움직이는 버스가 개발
             */
            bus.setMovableStrategy(new RailLoadStrategy());
            bus.move();
        }
    }

    5.3 예시 2 RPG게임

     

     

     

     

     

     

    참고자료: https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EC%A0%84%EB%9E%B5Strategy-%ED%8C%A8%ED%84%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EC%9E%90

     

    💠 전략(Strategy) 패턴 - 완벽 마스터하기

    Strategy Pattern 전략 패턴은 실행(런타임) 중에 알고리즘 전략을 선택하여 객체 동작을 실시간으로 바뀌도록 할 수 있게 하는 행위 디자인 패턴 이다. 여기서 '전략'이란 일종의 알고리즘이 될 수

    inpa.tistory.com

     

    https://refactoring.guru/ko/design-patterns/strategy

     

    전략 패턴

    / 디자인 패턴들 / 행동 패턴 전략 패턴 다음 이름으로도 불립니다: Strategy 의도 전략 패턴은 알고리즘들의 패밀리를 정의하고, 각 패밀리를 별도의 클래스에 넣은 후 그들의 객체들을 상호교환

    refactoring.guru

    https://victorydntmd.tistory.com/292

     

    [디자인패턴] 전략 패턴 ( Strategy Pattern )

    전략 패턴 ( Strategy Pattern )객체들이 할 수 있는 행위 각각에 대해 전략 클래스를 생성하고, 유사한 행위들을 캡슐화 하는 인터페이스를 정의하여,객체의 행위를 동적으로 바꾸고 싶은 경우 직접

    victorydntmd.tistory.com

    https://edu.nextstep.camp/

     

    NEXTSTEP

     

    edu.nextstep.camp

     

Designed by Tistory.