ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Flutter - 스트래티지 패턴 (Strategy pattern) 구현
    개발/flutter 2020. 9. 3. 16:54

    오리라는 클래스를 정의하려 한다.

    오리는 이런저런 오리들이 있다. 청둥오리, 까만 오리, 하얀 오리, 고무 오리, 장난감 오리.... 

    확장성 있는 앱을 만들려면 더 많은 새로운 신개념의 오리가 생겨 날 수 있다.

    나는 오리, 날지 못하는 오리,  우는 오리 , 울지 못하는 오리, 

    class MallardDuck{
    	void fly(){
        	print('i can fly');
        }
        void quack(){
        	print('quack quack quack...');
        }
        void swim(){
        	print('i can swim');
        }
    }
    
    class ToyDuck{
    	void fly(){
        	print('i cant fly');
        }
        void quack(){
        	print('...');
        }
        void swim(){
        	print('i can swim');
        }
    }
    
    
    

     

    이렇게 매번 새로운 오리에 swim() fly() quack() 함수를 정의해줘야 한다.

    그러나 fly() quack() 함수와 다르게 swim() 함수의 경우 중복이 발생하게 된다.

     

    중복을 방지하기 위해 Duck이라는 슈퍼 클래스를 만들고

    하위 클래스들이 상속을 받으면 된다. 그러고 슈퍼클래스와 다른 경우 오버라이드를 하면 된다.

    class Duck{
    	void fly(){
        	print('i can fly');
        }
        void quack(){
        	print('quack quack quack...');
        }
        void swim(){
        	print('i can swim');
        }
    
    }
    
    
    class MallardDuck extends Duck{
    	
    }
    
    class ToyDuck extends Duck{
    	void fly(){
        	print('i cant fly');
        }
        void quack(){
        	print('...');
        }
        
    }
    
    
      var mallardDuck = MallardDuck();
      mallardDuck.fly(); //  i can fly
      mallardDuck.swim();  //i can swim
    
    
      var modelDuck = ModelDuck();
      modelDuck.fly(); //i cant fly
      modelDuck.quack(); //...
      
    
    

     

     

    중복을 피했으나 매번 새로운 오리가 생길 때마다 날지 못하는지 울지 못하는지 다 따로 오버 라이딩을 해줘야 한다.

    이런 경우 추상 클래스와 구현 클래스를 만들어 다형화할 수 있다.

    예로 Fly라는 행동에 대한 추상 클래스(인터페이스)를 만들고

    날 수 있는 구현 클래스 날지 못하는 구현 클래스를 만들어

    추상 클래스를 implements 해주는 것이다.

     

     //추상 클래스
    abstract class FlyBehavior{ 
      void fly(); 
    }
    abstract class QuackBehavior{
      void quack();
     
    }
     //구현 클래스
    class FlyWithWings implements FlyBehavior{  
      fly(){
           print('fly with wings');
      }
    }
        
    
    class FlyNoWay implements FlyBehavior{
      fly(){
           print('I can"t fly') ; 
      }
    }
    
    class FlyRocketPowered implements FlyBehavior{
      fly(){
           print('pshhh@@!!') ; 
      }
    }
    
    class Quack implements QuackBehavior{
      quack(){
          print('Quack@!');
      }
    }
    
    class QuackNoWay implements QuackBehavior{
      quack(){
          print('...');
      }
    }
    
    class Duck{
      FlyBehavior flyBehavior;
      QuackBehavior quackBehavior;
      
      void performQuack(){
        quackBehavior.quack();
      }
      void performFly(){
        flyBehavior.fly();
      }
      
      setFlyBehavior(FlyBehavior fb){
        flyBehavior = fb;
        
      }
      setQuackBehavior(QuackBehavior qb){
         quackBehavior = qb;
      }
      
    }
    

     

    이후 Duck 클래스에 각 추상 클래스 변수를 만들어주고 set/perform 할 수 있는 함수를 만들어주면

    자식 클래스를 만들면서 구현 클래스를 넣어 줄 수 있고 혹은 set을 통해 구현 클래스를 넣어줄 수 있다.

    class MallardDuck extends Duck{
      MallardDuck(){
        quackBehavior = Quack();
        flyBehavior = FlyWithWings();
      }
    }
      var mallardDuck = MallardDuck();
    
    
      mallardDuck.performFly(); //fly with wings
      mallardDuck.performQuack(); //Quack@!
      mallardDuck.setFlyBehavior(FlyRocketPowered());
      mallardDuck.performFly(); //pshhh@@!!
    

     

    이렇게 되면 우는 행동 / 나는 행동이 캡슐화되었고 

    Duck 은 그 행동들을 사용한다.

    이렇게 하면 행동(알고리즘)을 Duck(클라이언트)와 구별해 독립적으로 변경할 수 있다.

    이를 스트래티지(Strategy) 패턴이라 한다. 

    댓글

Designed by Tistory.