객체지향 및 기반 언어/디자인 패턴

[Design Pattern] Chapter 01 디자인 패턴 소개와 전략 패턴

박지환 2022. 9. 25. 05:14

객체지향 기초

객체지향의 핵심 기초 4가지를 통해 디자인 패턴이 구현된다.

  • 추상화(Abstraction): 공통의 속성이나 기능을 묶어 이름을 붙이는 것
  • 상속(Inheritance): 상위 개념의 특징을 하위 개념이 물려받는 것
  • 다형성(Polymorphism): 하나의 변수, 함수가 상황에 따라 다른 의미로 해석할 수 있는 것
  • 캡슐화(Encapsulation): 데이터 구조와 데이터를 다루는 방법들을 결합 시켜 묶는 것

객체지향 원칙

디자인 원칙 1: 애플리케이션에서 달라지는 부분을 찾아내고, 달라지지 않는 부분과 분리한다.
디자인 원칙 2: 구현보다는 인터페이스에 맞춰서 프로그래밍한다.
디자인 원칙 3: 상속보다는 구성(composition)을 활용한다.

첫번째 디자인 패턴: 전략 패턴

전략 패턴(Strategy Pattern)은 알고리즘군을 정의하고 캡슐화해서 각각의 알고리즘군을 수정해서 쓸 수 있게 해 준다. 전략 패턴을 사용하면 클라이언트로부터 알고리즘을 분리해서 독립적으로 변경할 수 있다.

클래스의 행동(알고리즘)을 다른 클래스에 위임하고, 위임을 받은 클래스가 알고리즘을 구현하는 방식으로 구현된다.

전략 패턴 UML

인터페이스를 정의하고, 인터페이스를 구현하는 구상 클래스들을 둔다.

클라이언트가 인터페이스들을 통해 알고리즘군 안에서 특정 알고리즘을 선택할 수 있다. (보통 클라이언트의 생성자 또는 setter 메소드를 통해 특정 알고리즘을 선택함)

전략 패턴 예제 코드

public abstract class Duck {

    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public Duck() { }

    public abstract void display();

    public void performFly() {
        flyBehavior.fly();
    }

    public void performQuack() {
        quackBehavior.quack();
    }

    public void swim() {
        System.out.println("모든 오리는 물에 뜹니다. 가짜 오리도 뜨죠");
    }

    public void setFlyBehavior(FlyBehavior fb) {
        flyBehavior = fb;
    }

    public void setQuackBehavior(QuackBehavior qb) {
        quackBehavior = qb;
    }
}

Duck 클래스는 FlyBehavior와 QuackBehavior를 구성(Composition)으로 가지면서, 실제 행동은 Bahavior 클래스들에게 위임한다.

public interface FlyBehavior {

    public void fly();
}
public class FlyNoWay implements FlyBehavior {

    @Override
    public void fly() {
        System.out.println("저는 못 날아요");
    }
}
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("날고 있어요!");
    }
}

FlyBehavior 인터페이스를 통해 구상 클래스들은 fly()를 각자만의 알고리즘으로 구현한다. 이들이 모여서 알고리즘군이 된다. QuackBehavior 인터페이스와 하위 구상 클래스들도 같은 구성으로 이루어진다.

public class ModelDuck extends Duck {

    public ModelDuck() {
        flyBehavior = new FlyNoWay();
        quackBehavior = new Quack();
    }

    @Override
    public void display() {
        System.out.println("저는 모형 오리입니다");
    }
}
public class MullardDuck extends Duck {

    public MullardDuck() {
        flyBehavior = new FlyWithWings();
        quackBehavior = new Quack();
    }

    @Override
    public void display() {
        System.out.println("저는 물오리입니다");
    }
}

ModelDuck과 MallardDuck은 Duck 추상 클래스를 상속 받으며, 각자 다른 Behavior 알고리즘 구상 클래스들을 생성자에서 주입한다.

public class MiniDuckSimulator {

    public static void main(String[] args) {
        Duck mallard = new MullardDuck();
        mallard.performQuack();
        mallard.performFly();

        Duck model = new ModelDuck();
        model.performFly();
        model.setFlyBehavior(new FlyRocketPowered());
        model.performFly();
    }
}

ModelDuck과 MallardDuck은 같은 메소드를 호출하지만, 다른 알고리즘을 호출하게 된다. 또한 중간에 다른 Behavior 알고리즘을 주입하여 동적으로 Behavior 알고리즘을 바꿀 수 있다.

디자인 패턴 만나기

디자인 패턴: 소프트웨어 디자인에서 특정 문맥에서 공통적으로 발생하는 문제에 대해 재사용 가능한 해결책

핵심 정리

  • 객체지향 기초 지식만 가지고는 휼륭한 객체지향 디자이너가 될 수 없음.
  • 휼륭한 객체지향 디자인이라면 재사용성, 확장성, 관리의 용이성을 갖출 줄 알아야 함.
  • 패턴은 훌륭한 객체지향 디자인 품질을 갖추고 있는 시스템을 만드는 방법을 제공함.
  • 패턴은 검증받은 객체지향 경험의 산물임.
  • 패턴이 코드를 바로 제공하는 것은 아님. 디자인 문제의 보편적인 해법을 제공함. 특정 애플리케이션에 패턴을 적용하는 것은 스스로 해야 함.
  • 패턴은 발명되는 것이 아니라 발견되는 것임.
  • 대부분의 패턴과 원칙은 소프트웨어의 변경 문제와 연관되어 있음.
  • 대부분의 패턴은 시스템의 일부분을 나머지 부분과 무관하게 변경하는 방법을 제공함.
  • 많은 경우에 시스템에서 바뀌는 부분을 골라내서 캡슐화해야 함.
  • 패턴은 다른 개발자와의 의사소통을 극대화하는 전문 용어 역할을 함.

 

GitHub Code Reference: https://github.com/Krapi0314/Design_Patterns

 

GitHub - Krapi0314/Design_Patterns: Java Implementation of GoF's Design Patterns

Java Implementation of GoF's Design Patterns. Contribute to Krapi0314/Design_Patterns development by creating an account on GitHub.

github.com

Reference: http://www.yes24.com/Product/Goods/108192370

 

헤드 퍼스트 디자인 패턴 - YES24

유지관리가 편리한 객체지향 소프트웨어 만들기!“『헤드 퍼스트 디자인 패턴(개정판)』 한 권이면 충분하다.이유 1. 흥미로운 이야기와 재치 넘치는 구성이 담긴 〈헤드 퍼스트〉 시리즈! 하나

www.yes24.com