공부일지

전략패턴 본문

코딩/디자인패턴

전략패턴

이하택 2023. 9. 25. 22:23

<markdown> <markdown>

전략 패턴(Strategy Pattern)

소개

💡
특정 특정 작업을 정의해놓고 A,B,C 작업을 동적으로 교체하도록 하는 패턴
  • 알고리즘을 캡슐화하여 동적으로 교체할 수 있는 구조를 제공.
  • 정책 패턴(Policy Pattern)이라고도 불림.
  • 함수를 캡슐화해서 사용할 수도 있음을 인지하고 있자.

전략 패턴의 구성 요소

  1. 전략(Strategy) 인터페이스는 알고리즘을 정의하는 메서드를 선언합니다.
  1. 구체적인 전략(Concrete Strategies) 클래스는 전략 인터페이스를 구현하여 실제 알고리즘을 제공합니다.
  1. 컨텍스트(Context) 클래스는 전략을 사용하여 작업을 수행합니다.

전략 패턴의 예제

  • “여러 종류의 오리를 구현하고 싶다”

    ↪Fly기능을 추가하고 싶다.

    ↪그러나 가령 RubberDuck(고무오리) 등의 오리는 날 수 없기 때문에,

    슈퍼 클래스에 메서드를 추가하는 것은 적합하지 않다.

    ↪물론 Override할 수 있겠지만, 오리의 개수와 종류가 점점 추가된다면 계속해서 Override해야 할 것이다.

    • 해결책

      ↪따라서 우리는 하나의 슈퍼 클래스에서 유지되는 부분(공통된 부분)과 달라지는 부분(차이나는 부분)으로 분리해야한다.

      • 이것을 캡슐화라고 한다.

      이에 따라 우리는 위의 구성요소에서 말했 듯 인터페이스를 사용한다.

    • 예제 코드
      // 행동 인터페이스
      public interface IFlyBehavior
      {
          void Fly();
      }
      
      public interface IQuackBehavior
      {
          void Quack();
      }
      // 날 수 있는 행동 구현
      public class FlyWithWings : IFlyBehavior
      {
          public void Fly()
          {
              Console.WriteLine("날개로 납니다.");
          }
      }
      
      // 날지 못하는 행동 구현
      public class FlyNoWay : IFlyBehavior
      {
          public void Fly()
          {
              Console.WriteLine("날지 못합니다.");
          }
      }
      
      // 꽥꽥 소리를 내는 행동 구현
      public class Quack : IQuackBehavior
      {
          public void Quack()
          {
              Console.WriteLine("꽥꽥 소리를 냅니다.");
          }
      }
      
      // 삑삑 소리를 내는 행동 구현
      public class Squeak : IQuackBehavior
      {
          public void Quack()
          {
              Console.WriteLine("삑삑 소리를 냅니다.");
          }
      }
      public abstract class Duck
      {
          protected IFlyBehavior flyBehavior;
          protected IQuackBehavior quackBehavior;
      
          public Duck()
          {
          }
      
          public abstract void Display();
      
          public void PerformFly()
          {
              flyBehavior.Fly();
          }
      
          public void PerformQuack()
          {
              quackBehavior.Quack();
          }
      
          public void Swim()
          {
              Console.WriteLine("모든 오리는 물에 뜹니다.");
          }
      }
      public class MallardDuck : Duck
      {
          public MallardDuck()
          {
              flyBehavior = new FlyWithWings();
              quackBehavior = new Quack();
          }
      
          public override void Display()
          {
              Console.WriteLine("Mallard 오리");
          }
      }
      
      public class RubberDuck : Duck
      {
          public RubberDuck()
          {
              flyBehavior = new FlyNoWay();
              quackBehavior = new Squeak();
          }
      
          public override void Display()
          {
              Console.WriteLine("Rubber 오리");
          }
      }
      class Program
      {
          static void Main(string[] args)
          {
              Duck mallardDuck = new MallardDuck();
              Duck rubberDuck = new RubberDuck();
      
              mallardDuck.Display();
              mallardDuck.PerformFly();
              mallardDuck.PerformQuack();
      
              rubberDuck.Display();
              rubberDuck.PerformFly();
              rubberDuck.PerformQuack();
          }
      }

  • 상점 시스템 구현
    • 할인율

      상점에서 주문 시스템을 구현한다고 가정해봅시다.

      주문 처리 시스템은 다양한 할인 전략을 적용할 수 있어야 하며, 각 주문에 대한 할인을 유연하게 관리할 수 있어야 합니다.

      • 예제 코드
        // 할인 전략 인터페이스
        public interface IDiscountStrategy
        {
            double ApplyDiscount(double amount);
        }
        // 고정 금액 할인 전략
        public class FixedDiscountStrategy : IDiscountStrategy
        {
            private double discountAmount;
        
            public FixedDiscountStrategy(double amount)
            {
                discountAmount = amount;
            }
        
            public double ApplyDiscount(double amount)
            {
                return amount - discountAmount;
            }
        }
        
        // 백분율 할인 전략
        public class PercentageDiscountStrategy : IDiscountStrategy
        {
            private double percentage;
        
            public PercentageDiscountStrategy(double percent)
            {
                percentage = percent;
            }
        
            public double ApplyDiscount(double amount)
            {
                return amount * (1 - (percentage / 100));
            }
        }
        
        // 할인 없음 전략
        public class NoDiscountStrategy : IDiscountStrategy
        {
            public double ApplyDiscount(double amount)
            {
                return amount;
            }
        }
        public class Order
        {
            private IDiscountStrategy discountStrategy;
            private double totalAmount;
        
            public Order(IDiscountStrategy strategy)
            {
                discountStrategy = strategy;
            }
        
            public void AddItem(double price)
            {
                totalAmount += price;
            }
        
            public double CalculateTotal()
            {
                return discountStrategy.ApplyDiscount(totalAmount);
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Order order1 = new Order(new FixedDiscountStrategy(10)); // 10 달러 할인
                order1.AddItem(50); // 50 달러 상품 추가
                order1.AddItem(30); // 30 달러 상품 추가
                double total1 = order1.CalculateTotal();
                Console.WriteLine("첫 번째 주문의 총액: " + total1 + " 달러");
        
                Order order2 = new Order(new PercentageDiscountStrategy(20)); // 20% 할인
                order2.AddItem(100); // 100 달러 상품 추가
                order2.AddItem(75); // 75 달러 상품 추가
                double total2 = order2.CalculateTotal();
                Console.WriteLine("두 번째 주문의 총액: " + total2 + " 달러");
        
                Order order3 = new Order(new NoDiscountStrategy()); // 할인 없음
                order3.AddItem(40); // 40 달러 상품 추가
                double total3 = order3.CalculateTotal();
                Console.WriteLine("세 번째 주문의 총액: " + total3 + " 달러");
            }
        }

    • 주문처리

      예를 들어, 일부 주문은 신용 카드로 처리되고, 일부 주문은 현금으로 처리될 수 있습니다. 이러한 주문 처리 방식을 각각의 전략 클래스로 구현하고, 컨텍스트 클래스에서 해당 전략을 선택하여 주문을 처리할 수 있습니다.

전략 패턴의 장점

  1. 유연성
  1. 확장성
  1. 재사용성
  1. 테스트의 용이함

결론

우리는 상속으로 코드의 재사용성과 유연성을 높일 수 있다.

그러나 코드의 전체적인 이해도가 부족하다면 오히려 예외 처리에 있어서 서브 클래스에 악영향을 끼쳐서 불필요한 코드 중복이 발생할 수 있다.

이런 경우, 전략 패턴으로 알고리즘의 동적 교체와 재사용성을 제공하여 코드의 유연성을 높여 보완할 수 있다.


Reference

Strategy Pattern(전략 패턴)이란?
🚀 전략 패턴이란? 정책 패턴(Policy Pattern)이라고도 불림 알고리즘군을 정의하고 캡슐화해서 각각의 알고리즘군을 수정해서 사용할 수 있게 해줌 객체의 행위를 변경하고 싶은 경우 직접 수정하지 않고 전략이라 불리는 캡슐화한 알고리즘을 변경해줌으로써 유연하게 확장하는 방법 🚀 강아지로 예시 코드 작성해보기 먼저 강아지를 만들어야한다고 생각합니다. 강아지는 다양하고, 각각 행동(소리와 움직임)이 다릅니다. 이 때 어떻게 코드를 작성할 수 있을까요? 1. 상속을 이용 같은 행동을 하는 강아지들이라면 상관없지만 다른 행동을 하는 강아지들이 있을 수 있습니다. 코드 재사용성을 위해 상속을 이용하는 것도 좋지만, 불필요한 유지보수가 크게 늘어날 수 있습니다. 즉, 모든 서브클래스에서 같은 행동을 하는 것이..
https://ssdragon.tistory.com/140
[디자인패턴] 전략 패턴 ( Strategy Pattern )
전략 패턴 ( Strategy Pattern )객체들이 할 수 있는 행위 각각에 대해 전략 클래스를 생성하고, 유사한 행위들을 캡슐화 하는 인터페이스를 정의하여,객체의 행위를 동적으로 바꾸고 싶은 경우 직접 행위를 수정하지 않고 전략을 바꿔주기만 함으로써 행위를 유연하게 확장하는 방법을 말합니다. 간단히 말해서 객체가 할 수 있는 행위들 각각을 전략으로 만들어 놓고, 동적으로 행위의 수정이 필요한 경우 전략을 바꾸는 것만으로 행위의 수정이 가능하도록 만든 패턴입니다. 1. 전략 패턴 사용 이유예를 들어, 기차( Train )와 버스( Bus ) 클래스가 있고, 이 두 클래스는 Movable 인터페이스를 구현했다고 가정하겠습니다. 그리고 Train과 Bus 객체를 사용하는 Client도 있습니다. 이 구조..
https://victorydntmd.tistory.com/292
전략 패턴
전략 패턴은 알고리즘들의 패밀리를 정의하고, 각 패밀리를 별도의 클래스에 넣은 후 그들의 객체들을 상호교환할 수 있도록 하는 행동 디자인 패턴입니다.
https://refactoring.guru/ko/design-patterns/strategy
내일배움캠프
국비지원 코딩, 내일배움캠프는 개발자 취업까지 자신 있습니다. 기간 제한 없는 취업 컨설팅을 받으며 비전공자 IT취업 준비, 확실히 끝내세요.
https://nbcamp.spartacodingclub.kr/game

Uploaded by N2T

'코딩 > 디자인패턴' 카테고리의 다른 글

옵저버 패턴[작성중]  (0) 2023.10.30
풀 매니저  (0) 2023.10.19