본문 바로가기

(4)

전략 패턴 (Strategy Pattern)

전략 패턴 (Strategy Pattern) 인터페이스란.. 사전적 정의 키보드나 디스플레이 따위처럼 사람과 컴퓨터를 연결하는 장치 컴퓨터 언어에서의 정의 기능에 대한 선언과 구현 분리 기능을 사용하는 통로 A 라는 기능이 있고, 이를 인터페이스를 통해 구현한다고 했을 때, 인터페이스는 아래와 같다. public interface Ainterface { //기능의 선언 public void funcA(); } 구현은 Class에서 A Interface를 implements로 받아서 구현할 수 있다. public class AinterfaceImpl implements Ainterface { @Override public void funcA() { System.out.println("AAA"); } } 델..

3. 브릿지 패턴 (Bridge Pattern)

지난 [디자인 패턴] - 2. 어댑터 패턴 (Adapter Pattern)에 이어서 유사한 형태의 브릿지 패턴에 대해 설명해보려고 한다. 브릿지 패턴이란.. 브릿지 패턴은 "구현(implementation)으로부터 추상(abstraction) 레이어를 분리하여 이 둘이 서로 독립적으로 변화할 수 있도록 한다." 즉 기능과 구현에 대해서 두 개를 별도의 클래스로 구현을 한다. (두개의 다른 계층은 하나는 추상, 하나는 구현이다. 이는 서로 다른 계층의 커플링을 약화시키며 협력은 가능하도록 하는 패턴이다) 브릿지 패턴 클래스 다이어그램 Abstraction 기능 계층의 최상위 클래스이며 추상 인터페이스를 정의한다. Implementor에 대한 레퍼런스를 유지한다. 구현 부분에 해당하는 클래스를 인스턴스를 가..

2. 어댑터 패턴 (Adapter Pattern)

저번 강의 [디자인 패턴] - 1. 전략(Strategy) 패턴 에 이어서 이번 포스팅에는 '어댑터 패턴'에 대한 내용을 정리하고자 한다. 어댑터 패턴이란... 어댑터 패턴은 연관성이 없는 두 객체를 묶어 사용할 때 쓰이는 패턴이다. (= 클라이언트가 요구하는 인터페이스와 재사용하려는 모듈의 인터페이스가 일치하지 않을 때 사용할 수 있는 패턴) 어댑터 패턴이 적용된 예는 SLF4J라는 로깅 API이다. SLF4J는 단일 로깅 API를 사용하면서 자바 로깅, log4j, LogBack 등의 로깅 프레임워크를 선택적으로 사용할 수 있도록 해 주는데, 이 때 SLF4J가 제공하는 인터페이스와 각 로깅 프레임워크를 맞춰 주기 위해 어댑터를 사용하고 있다. 어댑터 패턴은 (SOLID 원칙에서 OCP)개방 폐쇄 원..

1. 전략(Strategy) 패턴

특정 디자인 패턴을 정리하기 이전에 기본적으로 디자인 패턴이 뭔지 알아야 할 것이다. 디자인 패턴이란? 객체 지향 설계는 소프트웨어로 해결하고자 하는 문제를 다루면서, 동시에 재설계 없이 또는 재설계를 최소화하면서 요구 사항의 변화를 수용할 수 있도록 만들어 준다. 객체 지향 설계를 하다 보면, 이전과 비슷한 상황에서 사용했던 설계를 재사용하는 경우가 발생한다. 이런 설계는 특정 상황에 맞는 해결책을 빠르게 찾을 수 있도록 도와주는데, 이렇게 반복적으로 사용되는 설계는 클래스, 객체의 구성, 객체 간 메시지 흐름에서 일정 패턴을 갖는다. 이런 패턴을 습득함으로써 다음과 같은 이득을 얻을 수 있다. 상황에 맞는 올바른 설계를 더 빠르게 적용할 수 있다. 각 패턴의 장단점을 통해서 설계를 선택하는데 도움을 ..

디자인 패턴

전략 패턴 (Strategy Pattern)

728x90

전략 패턴 (Strategy Pattern)

인터페이스란..

사전적 정의

  • 키보드나 디스플레이 따위처럼 사람과 컴퓨터를 연결하는 장치

    컴퓨터 언어에서의 정의

  • 기능에 대한 선언과 구현 분리
  • 기능을 사용하는 통로

A 라는 기능이 있고, 이를 인터페이스를 통해 구현한다고 했을 때, 인터페이스는 아래와 같다.

public interface Ainterface {
    //기능의 선언 
    public void funcA();
}

구현은 Class에서 A Interface를 implements로 받아서 구현할 수 있다.

public class AinterfaceImpl implements Ainterface {

    @Override
    public void funcA() {
        System.out.println("AAA");
    }
}

델리게이트(Delegate)란..

  • 위임하다

인터페이스: 기능을 기능의 선언과 기능의 구현을 분리할 수 있는 기능을 제공한다. 또한 어떤 기능을 호출하는 통로의
델리게이트: 특정 객체의 기능을 사용하기 위해, 다를 객체의 기능을 호출하는 것

전략 패턴이란..?

  • 여러 알고리즘을 하나의 추상적인 접근점을 만들어 접근점에서 서로 교환 가능하도록 하는 패턴.

일반적인 전략 패턴 설계

image

전략패턴의 예

(게임에서 캐릭터와 무기의 예)

요구 사항

  • 신작 게임에서 캐릭터와 무기를 구현하시오
  • 무기는 두 가지 종류가 있다
public interface Weapon {

    public void attack();

}
public class Knife implements Weapon {

    @Override
    public void attack() {
        System.out.println("칼 공격");
    }
}
public class Sword implements Weapon {

    @Override
    public void attack() {
        System.out.println("검 공격");
    }
}
public class Ax implements Weapon {

    @Override
    public void attack() {
        System.out.println("도끼 공격");
    }
}
pubic class GameCharacter {
    // 접근점
    private Weapon weapon;

    // 교환 가능 
    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }

    public void attack() {
        if (weapon == null) {
            System.out.prinlnt("맨손 공격");
        }

        // 델리게이트 (내가 어떤 것을 들고 있는지에 따라서 공격 형태가 바뀐다, Weapon이 알아서 할 것이다)
        weapon.attack();
    }    
}
public class Main {

    public static void main(String[] args) {
        GameCharacter character = new GameCharacter();

        character.attack(); 

        character.setWeapon(new Knife());
        character.attack();

        character.setWeapon(new Sword());
        character.attack();

        character.setWeapon(new Ax());
        character.attack();
    }
}
728x90

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

3. 브릿지 패턴 (Bridge Pattern)  (0) 2020.04.25
2. 어댑터 패턴 (Adapter Pattern)  (0) 2020.04.24
1. 전략(Strategy) 패턴  (0) 2020.04.18
디자인 패턴

3. 브릿지 패턴 (Bridge Pattern)

728x90

지난 [디자인 패턴] - 2. 어댑터 패턴 (Adapter Pattern)에 이어서 유사한 형태의 브릿지 패턴에 대해 설명해보려고 한다. 

브릿지 패턴이란.. 

브릿지 패턴은 "구현(implementation)으로부터 추상(abstraction) 레이어를 분리하여 이 둘이 서로 독립적으로 변화할 수 있도록 한다." 

기능구현에 대해서 두 개를 별도의 클래스로 구현을 한다. (두개의 다른 계층은 하나는 추상, 하나는 구현이다. 이는 서로 다른 계층의 커플링을 약화시키며 협력은 가능하도록 하는 패턴이다) 

 

브릿지 패턴 클래스 다이어그램

Abstraction

  • 기능 계층의 최상위 클래스이며 추상 인터페이스를 정의한다. Implementor에 대한 레퍼런스를 유지한다. 
  • 구현 부분에 해당하는 클래스를 인스턴스를 가지고 해당 인스턴스를 통해 구현부분의 메서드를 호출한다. 

RefinedAbstraction

  • Abstraction에 의해 정의된 인터페이스를 확장한다. (extends)
  • 기능 계층에서 새로운 부분을 확장한 클래스이다.

Implementor

  • 구현 클래스를 위한 인터페이스를 정의한다.
  • Abstraction의 기능을 구현하기 위한 인터페이스를 정의한다. 

ConcreteImplementor

  • Implementor 인터페이스를 구현 즉, 실제 기능을 구현한다.

브릿지 패턴의 예를 설명한만한 예제를 찾아보았는데... 참고 글의 예제가 제일 적절하면서 이해도 잘 되는것 같다. 예제를 그대로 뺏겨서 적는건 좀 아니라고 생각이 들어서 예제는 이 글을 참조하자! 

 

 

브릿지 패턴과 어댑터 패턴의 차이 

먼저 두 패턴 모두 Interface의 detail을 감추고자 하며, 구조적인 차이가 없다.

하지만 두 패턴은 서로 사용하는 목적이 다르다! 

어댑터 패턴 : 어떤 클래스의 인터페이스가 다른 코드에서 기대하는 것과 다를 때 어댑터를 중간에 두어 맞춰주는 것 
브릿지 패턴 : 추상과 구현을 분리하는 것 (추상 클래스와 구현의 변경이 서로 영향을 주지 않도록 한다) 

 

참고 영상: 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/lecture/3190

 

자바 디자인 패턴의 이해 - Gof Design Pattern - 인프런

자바 디자인 패턴 이해하기 강좌 입니다. 여러가지 디자인 패턴들을 알아보며 디자인 패턴에 대한 이해도를 높이도록 도와줍니다. Gof Design Pattern을 자바 언어로 설명한 강의. 의미 있고 쉬운 예제를 준비하려고 노력했습니다. 중급 프로그래밍 언어 Java MVC 온라인 강의 자바 디자인 패턴

www.inflearn.com

참고 글 : https://www.crocus.co.kr/1537

 

브릿지 패턴(Bridge Pattern)

브릿지 패턴(Bridge Pattern) 브릿지 패턴은 아래와 같이 정의한다. "구현(implementation)으로부터 추상(abstraction) 레이어를 분리하여 이 둘이 서로 독립적으로 변화할 수 있도록 한다." "구현부에서 추상층을..

www.crocus.co.kr

 

728x90

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

전략 패턴 (Strategy Pattern)  (0) 2020.10.02
2. 어댑터 패턴 (Adapter Pattern)  (0) 2020.04.24
1. 전략(Strategy) 패턴  (0) 2020.04.18
디자인 패턴

2. 어댑터 패턴 (Adapter Pattern)

728x90

저번 강의 [디자인 패턴] - 1. 전략(Strategy) 패턴 에 이어서 이번 포스팅에는 '어댑터 패턴'에 대한 내용을 정리하고자 한다.

어댑터 패턴이란... 

어댑터 패턴은 연관성이 없는 두 객체를 묶어 사용할 때 쓰이는 패턴이다. (= 클라이언트가 요구하는 인터페이스와 재사용하려는 모듈의 인터페이스가 일치하지 않을 때 사용할 수 있는 패턴)

어댑터 패턴이 적용된 예는 SLF4J라는 로깅 API이다. SLF4J는 단일 로깅 API를 사용하면서 자바 로깅, log4j, LogBack 등의 로깅 프레임워크를 선택적으로 사용할 수 있도록 해 주는데, 이 때 SLF4J가 제공하는 인터페이스와 각 로깅 프레임워크를 맞춰 주기 위해 어댑터를 사용하고 있다. 

어댑터 패턴은 (SOLID 원칙에서 OCP)개방 폐쇄 원칙을 따를 수 있도록 도와준다. (예를들어 로깅 프레임워크를 LogBack으로 교체하고 싶다면 LogBack을 slf4j-api 패키지의 Logger로 맞춰주는 새로운 어댑터만 구현해 주면 된다. 그리고 이 과정에서 slf4j-api 패키지의 Logger를 사용하는 코드는 전혀 영향을 받지 않는다)

 

예제 

웹 게시판에 통합 검색 기능을 추가해 달라는 요구가 들어와서 DB를 이용해서 검색 기능을 구현하기로 결정한 상황을 생각해 보자. 통합 검색 기능을 정의하기 위해 아래와 같이 SearchService 인터페이스를 작성하고, DB를 이용한 DBSearchService 클래스를 구현하였다. 

 

게시글의 개수가 빠르게 증가하면서 SQL의 like를 이용한 검색 속도 성능에 문제가 발생하기 시작했다. 검색 속도의 문제를 해결하기 위해 Tolr라는 오픈 소스 검색 서버를 도입하기로 결정했다. Tolr와 쉽게 연동할 수 있다는 것을 알게 되었다.

문제는 TolrClient가 제공하는 인터페이스와 SearchService 인터페이스가 맞지 않는다는 점이다. WebSearchRequestHandler 클래스를 비롯해서 여러 클래스가 SearchService를 사용하도록 만들어졌기 때문에, SearchService 대신 TolrService를 사용하도록 변경하는 작업은 많은 변경을 요구한다.

이렇게 클라이언트(WebSearchRequestHandler)가 요구하는 인터페이스(SearchService)와 재사용하려는 모듈의 인터페이스(TolrClient)가 일치하지 않을 때 사용할 수 있는 패턴 어댑터(Adapter) 패턴이다. 인터페이스가 맞지 않는 문제를 해결하기 위해 어댑터 패턴을 적용하면 아래와 같은 구조를 갖게 된다.

위 그림에서 어댑터에 해당하는 SearchServiceTolrAdapter 클래스는 TolrClient를 SearchService 인터페이스에 맞춰 주는 책임을 갖는다. SearchServiceTolrAdapter 클래스의 search() 메서드는 아래의 코드처럼 TolrClient 객체를 실행하고 그 결과를 SearchService 인터페이스에 맞는 리턴 타입으로 변환해 준다. (상속을 이용해서 어댑터를 구현하는 경우, SearchServiceTolrAdapter 클래스의 search() 메서드는 상위 클래스인 TolrClient에 정의된 메서드를 호출하는 방식으로 코드를 작성하게 된다)

public class SearchServiceTolrAdapter implements SearchService {
    private TolrClient tolrClient = new TolrClient();
    
    public SearchResult search(String keyword) {
        // keyword를 tolrClient가 요구하는 형식으로 변환
        TolrQuery tolrQuery = new TolrQuery(keyword);
        //TolrClient 기능 실행
        QueryResponse response = tolrClient.query(tolrQuery);
        //TolrClioent의 결과를 SearchResult로 변환
        SearchResult result = convertToResult(response);
        return result;
    }
    
    private SearchResult convertToResult(QueryResponse response) {
        List<TolrDocument> tolrDocs = response.getDocumentList().getDocuments();
        List<SearchDocument> docs = new ArrayList<SearchDocument>();
        for(TolrDocument tolrDoc : tolrDocs) {
            docs.add(new SearchDocument(tolrDoc.getId(), ...);
        }
        return new SearchResult(docs);
    }
}

 추가적으로 자바는 클래스 단일 상속만을 지원하기 때문에, 클라이언트가 사용하는 SearchService가 인터페이스가 아닌 일부 구현이 포함된 추상 클래스라면, 어댑터 구현에 제약을 받는다. 

 

참고 영상: 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/lecture/3173

 

자바 디자인 패턴의 이해 - Gof Design Pattern - 인프런

자바 디자인 패턴 이해하기 강좌 입니다. 여러가지 디자인 패턴들을 알아보며 디자인 패턴에 대한 이해도를 높이도록 도와줍니다. Gof Design Pattern을 자바 언어로 설명한 강의. 의미 있고 쉬운 예제를 준비하려고 노력했습니다. 중급 프로그래밍 언어 Java MVC 온라인 강의 자바 디자인 패턴

www.inflearn.com

참고 서적: 개발자가 반드시 정복해야 할 객체지향과 디자인 패턴

 

객체 지향과 디자인 패턴

객체 지향 안내서. 객체, 책임, 의존, 캡슐화 등 객체 지향의 주요 개념들을 쉬운 예제와 그림을 통해 이해하기 쉽게 설명한다.

www.yes24.com

 

728x90

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

전략 패턴 (Strategy Pattern)  (0) 2020.10.02
3. 브릿지 패턴 (Bridge Pattern)  (0) 2020.04.25
1. 전략(Strategy) 패턴  (0) 2020.04.18
디자인 패턴

1. 전략(Strategy) 패턴

728x90

특정 디자인 패턴을 정리하기 이전에 기본적으로 디자인 패턴이 뭔지 알아야 할 것이다. 

디자인 패턴이란? 

객체 지향 설계는 소프트웨어로 해결하고자 하는 문제를 다루면서, 동시에 재설계 없이 또는 재설계를 최소화하면서 요구 사항의 변화를 수용할 수 있도록 만들어 준다. 객체 지향 설계를 하다 보면, 이전과 비슷한 상황에서 사용했던 설계를 재사용하는 경우가 발생한다. 이런 설계는 특정 상황에 맞는 해결책을 빠르게 찾을 수 있도록 도와주는데, 이렇게 반복적으로 사용되는 설계는 클래스, 객체의 구성, 객체 간 메시지 흐름에서 일정 패턴을 갖는다. 이런 패턴을 습득함으로써 다음과 같은 이득을 얻을 수 있다. 

  • 상황에 맞는 올바른 설계를 더 빠르게 적용할 수 있다. 
  • 각 패턴의 장단점을 통해서 설계를 선택하는데 도움을 얻을 수 있다.
  • 설계 패턴에 이름을 붙임으로써 시스템의 문서화, 이해, 유지 보수에 도움을 얻을 수 있다. 

(이 분야에서 자주 사용되는 패턴들을 모아서 집대성한 다양한 책이 존재하는데, 그 중에서도 GoF의 디자인 패턴이 많은 프로그래머들에게 도움을 주었다)


전략(Strategy) 패턴

전략패턴은 특정 콘텍스트(Context)에서 알고리즘(전략)을 별도로 분리하는 설계 방법이다. 전략 패턴에서 콘텍스트는 사용할 전략을 직접 선택하지 않는다. 대신, 콘텍스트의 클라이언트가 콘텍스트에 사용할 전략을 전달해 준다. 그리고 전략이 어떤 메서드를 제공할 지의 여부는 콘텍스트가 전략을 어떤 식으로 사용하느냐에 따라 달라진다. 

조금 쉽게 얘기하자면(나름 쉽게 얘기하자면) 여러 알고리즘을 하나의 추상적인 접근점(여기서는 인터페이스)을 만들어 접근 점에서 서로 교환 가능하도록 하는 패턴이다.

기본적인 설계는 위의 그림과 같다. 

예를 들어보자! 

한 과일 매장이 상황에 따라 다른 가격 할인 정책을 적용하고 있고, 매장의 첫 손님을 위한 '첫 손님 할인' 정책과 저녁 시간대에 신선도가 떨어진 과일에 대한 '덜 신선한 과일 할인' 정책이 있다면, 아래와 같은 코드를 작성할 것이다. 

public class Calculator {
    public int calculate(boolean firstGuest, List<Item> items) {
        int sum = 0;
        for (Item item : items) {
            if (firstGuest) {
                sum += (int) (item.getPrice() * 0.9); // 첫 손님 할인
            } else if (!item.isFresh()) {
                sum += (int) (item.getPirce() * 0.8); // 덜 신선한 것 20% 할인
            } else {
                sum += item.getPrice();
            }
        return sum;
    }
}

딱히 이 코드가 틀렸다는 것은 아니다(다들 그렇게 생각할 것이다). 하지만 이 코드는 다음과 같은 문제점을 포함한다. 

  • 서로 다른 계산 정책들이 한 코드에 섞여 있어, 정책이 추가될수록 코드 분석을 어렵게 만든다. 
  • 가격 정책이 추가될 때마다 calculate 메서드를 수정하는 것이 점점 어려워진다. 

이런 문제를 해결하기 위한 방법 중의 하나는 '가격 할인 정책'을 별도 객체로 분리하는 것이다. 

이제부터 DiscountStrategy 인터페이스를 생성하여 상품의 할인 금액 계산을 추상화하고, 각 콘크리트 클래스(전략 콘크리트 클래스)는 상황에 맞는 할인 계산 알고리즘을 제공한다. Calculator 클래스는 가격 합산 계산의 책임을 진다. 

여기서 가격 할인 알고리즘(계산 방법)을 추상화하고 있는 DiscountStarategy를 전략(Strategy)이라고 부르고 가격 계산 기능 자체의 책임을 갖고 있는 Calculator를 콘텍스트(Context)라고 부르는데, 이렇게 특정 콘텍스트에서 알고리즘(전략)을 별도로 분리하는 설계 방법이 전략패턴이다. 

이제 전략 패턴을 적용한 Calculator를 구현한다(이제 Calculator는 변할 일이 없다). 

public class Calculator {
    private DiscountStrategy discountStrategy;
    
    public Calculator(DiscountStrategy discountStrategy) {
        this.discountStartegy = discountStartegy;
    }
    
    public int calculate(List<Item> items) {
        int sum = 0;
        for (Item item : items) {
            sum += discountStrategy.getDiscountPrice(item);
        }
        return sum;
    }
}

 

이제 위의 Calculator 클래스는 생성자를 통해서 사용할 전략 객체를 전달받고, calculate() 메서드에서 각 Item의 가격을 계산할 때 전략 객체를 사용하고 있다. 위 코드에서 Calculator는 각 Item 별로 할인 정책을 적용하고 있으므로 DiscountStrategy 인터페이스는 아래와 같이 정의 될 것이다. 

public interface DiscountStrategy {
    int getDiscountPrice(Item item);
}

만약 각 아이템 별로 할인 정책이 있고 전체 금액에 대한 할인 정책이 별도로 필요하다면 아래와 같이 전체 금액 할인을 위한 메서드를 추가한다. 

public interface DiscountStrategy {
    int getDiscountPrice(Item item);
    int getDiscountPrice(int totalPrice);
}

또는, 전체 금액 할인 정책을 위한 전략을 별도 인터페이스로 분리할 수도 있을 것이다. 

public interface ItemDiscountStrategy {
    int getDiscountPrice(Item item);
}

public interface TotalPriceDiscountStrategy {
    int getDiscountPrice(int totalPrice);
}

 

전략 객체는 콘텍스트를 사용하는 클라이언트에서 직접 생성한다. 예를 들어, 첫 번째 손님에 대한 할인 정책을 FirstGuestDiscountStrategy 구현 클래스로 구현한다고 하자. 

public class FirstGuestDiscountStrategy implements DiscountStrategy {
    
    @Override
    public int getDiscountPrice(Item item) {
        return (int) (item.getPrice() * 0.9);
    }
}

 

첫 번째 손님이 들어와서 계산을 하면, 계산기에서 첫 번째 손님 할인 적용 버튼을 누른 뒤에 계산 버튼을 누를 것이다. 이를 처리하는 코드는 다음과 같은 방식으로 작성될 것이다. 

private DiscountStrategy strategy;

public void onFirstGuestButtonClick() {
    // 첫 손님 할인 버튼 누를 때 생성
    strategy = new FirstGuestDiscountStrategy();
}

public void onCalculationButtonClick() {
    // 계산 버튼 누를 때 실행 
    Calculator cal = new Calculator(strategy);
    int price = cal.calculate(items);
    ...
}

위 코드를 보면 Calculator를 사용하는 코드에서 FirstGuestDiscountStrategy 클래스의 객체를 생성하는 것을알 수 있다. 이는 콘텍스트를 사용하는 클라이언트가 전략의 상세 구현에 대한 의존이 발생한다는 것을 뜻한다. 

콘텍스트의 클라이언트가 전략의 인터페이스가 아닌 상세 구현을 안다는 것이 문제처럼 보일 수 있지만, 이 경우에는 전략의 콘크리트 클래스와 클라이언트의 코드가 쌍을 이루기 때문에 유지 보수 문제가 발생할 가능성이 줄어든다. (또한 클라이언트의 버튼 처리 코드에서 전략 객체를 직접 생성하는 것이 오히려 코드 이해를 높이고 코드 응집을 높여 주는 효과를 갖는다)

전략 패턴을 적용할 때 얻을 수 있는 이점은 콘텍스트 코드의 변경 없이 새로운 전략을 추가할 수 있다는 점이다. 앞의 예제에서도 마지막 손님 대폭 할인 정책을 추가하는 경우, 계산의 틀인 Calculator 클래스의 코드는 변경되지 않는다. 단지 새로운 할인 정책을 구현한 LastGuestDiscountStrategy 클래스를 추가하고, 마지막 손님 대폭 할인 버튼 클릭을 처리하는 코드에서 LastGuestDiscountStrategy의 객체를 생성해 주기만 하면 된다. 

private DiscountStrategy strategy;

public void onLastGuestButtonClick() {
    // 마지막 손님 대폭 할인 버튼 누를 때 생성
    strategy = new LastGuestDiscountStrategy();
}

public void onCalculationButtonClick() {
    // 계산 버튼 누를 때 실행 됨
    Calculator cal = new Calculator(strategy);
    int price = cal.calculate(items);
    ...
}

전략 패턴을 적용함으로써 Calculator 클래스는 할인 정책 확장에는 열려 있고 변경에는 닫혀 있게 된다. 즉 '개방 폐쇄 원칙'(SOLID원칙의 OCP)을 따르는 구조를 갖게 된다. 

일반적으로 if-else로 구성된 코드 블록이 비슷한 기능(비슷한 알고리즘)을 수행하는 경우에 전략 패턴을 적용함으로써 코드를 확장 가능하도록 변경할 수 있다. (본 예제에서도 calculate() 메서드의 if-else 블록에 전략 패턴을 적용함으로써 새로운 할인 정책을 보다 쉽게 추가할 수 있도록 만들었다) 

 

이 외에도 완전히 동일한 기능을 제공하지만 성능의 장단점에 따라 알고리즘을 선택해야 하는 경우에도 전략패턴을 사용한다. 

 

 

참고도서: (개발자가 반드시 정복해야 할) 객체지향과 디자인 패턴

참고강의 : 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/lecture/3171

 

자바 디자인 패턴의 이해 - Gof Design Pattern - 인프런

자바 디자인 패턴 이해하기 강좌 입니다. 여러가지 디자인 패턴들을 알아보며 디자인 패턴에 대한 이해도를 높이도록 도와줍니다. Gof Design Pattern을 자바 언어로 설명한 강의. 의미 있고 쉬운 예제를 준비하려고 노력했습니다. 중급 프로그래밍 언어 Java MVC 온라인 강의 자바 디자인 패턴

www.inflearn.com

 

728x90

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

전략 패턴 (Strategy Pattern)  (0) 2020.10.02
3. 브릿지 패턴 (Bridge Pattern)  (0) 2020.04.25
2. 어댑터 패턴 (Adapter Pattern)  (0) 2020.04.24