[20220814_소프트 웨어 디자인 패턴]

YunTrollpark·2022년 8월 14일
0

관련 지식

목록 보기
5/7

소프트 웨어 디자인 패턴

과거 소프트웨어 개발 과정에서 발견된 설계의 노하우를 축적하여 그 방법에 이름을 붙여 재사용하기 좋은 형태로 특정 규약을 만들어서 정리한 것(모든 상황의 해결책은 아님)
“바퀴를 다시 발명하지 마라(Don’t reinvent the wheel)”

여기에는 생성 패턴 (Creational Patterns), 구조 패턴(Structural Patterns), 행위 패턴 (Behavioral Patterns) 이렇게 3가지 패턴이 있다.(Gang of Four 줄여서 GoF 디자인 패턴)

구분유형설명
목적 생성 패턴객체 인스턴스 생성에 관여, 클래스 정의와 객체 생성 방식을 구조화, 캡슐화를 수행하는 패턴
구조 패턴더 큰 구조 형성 목적으로 클래스나 객체의 조합을 다루는 패턴
행위 패턴클래스나 객체들이 상호작용하는 방법과 역할 분담을 다루는 패턴

표 출처: https://velog.io/@poiuyy0420/디자인-패턴-개념과-종류

1. 디자인 패턴의 장점

1) 자주 반복해서 발생하는 문제와 그 문제를 해결하는 핵심을 기술해 동일한 일을 두번 다시 하지 않고 해결할 수 있도록 한다.(재사용성이 높고, 프로그램의 최적화에 도움이 됨)

2) 구체적인 설명 없이 구조화된 패턴에 대한 사전 지식으로 개발자 간에 커뮤니케이션이 수월하다.(구구절절 설명하지 않고 ㅇㅇ패턴으로 해주세요.)

3) 설계 과정의 속도를 높일 수 있다. 이미 검증된 구조이기 때문이다.(과거 개발과정의 설계 노하우를 바탕으로 하기 때문)

2. 디자인 패턴의 단점

1) 객체지향적 설계를 고려하여 진행해야 한다.

2) 초기 투자 비용이 많이 들어감(돈 뿐만 아니라 시간 등 포함)

3. 디자인 패턴 종류

1) 생성 패턴 (Creational Patterns)

객체 생성 인스턴스에 관여, 객체의 생성과 조합을 캡슐화해 특정 객체가 생성 되거나 변경되어도 프로그램 구조에 영향을 크게 받지 않도록 유연성을 제공한다.

싱글톤 (Singleton): 인스턴스를 오직 1개 생성하고, 이후에는 이 인스턴스를 참조하는 패턴

팩토리 메소드 (Factory Method): 인스턴스를 만들어내는 공장(Factory)을 통해 객체를 생성하는 방법이다. 즉, 인스턴스를 직접 생성해내지 않고, 공장에서 제공하는 메쏘드를 통해 생성하는 패턴

추상 팩토리 (Abstract Factory): 공장을 만들어내는 상위 공장을 먼저 정의하고, 여기서 구체적인 공장을 만든 후, 이 공장에서 객체를 생성하는 패턴(팩토리의 위에 이 팩토리를 만드는 팩토리)

빌더 (Builder): 생산 단계를 캡슐화 하여 구축 공정을 동일하게 이용하도록 하는 패턴(객체를 생성할 때 필요한 파라미터가 많은 경우, 빌더라는 형태를 통해 파라미터 의미를 명확히하여 생성 가능)

프로토타입 (Prototype): 복사하여 새 개체를 생성할 수 있도록 하는 패턴

2) 구조 패턴 (Structural Pattern)

클래스나 객체를 조합해 더 큰 구조를 만드는 패턴으로 예를 들어, 서로 다른 인터페이스를 지닌 2개의 객체를 묶어 단일 인터페이스를 제공하거나 객체들을 서로 묶어 새로운 기능을 제공하는 패턴이다.

어댑터 (Adapter) : 클래스의 인터페이스를 어떤 클래스에서든 이용할 수 있도록 변환하는 패턴

브리지 (Bridge) : 구현부에서 추상층을 분리하여 각자 독립적으로 변형하고 확장할 수 있도록 하는 패턴

컴퍼지트 (Composite) : 개별 객체와 복합 객체를 클라이언트에서 동일하게 사용하도록 하는 패턴(그릇과 내용물을 동일시)

데코레이터 (Decorator) : 소스를 변경하지 않고 기능을 확장하도록 하는 패턴(장식과 내용물을 동일시)

파사드 (Facade) : 서브 시스템에 있는 인터페이스 집합에 대해 통합된 인터페이스를 제공하는 패턴

플라이웨이트 (Flyweight) : 크기가 작은 여러개의 객체를 매번 생성하지 않고 최대한 공유하여 사용하도록 메모리를 절약하게 해주는 패턴(대량의 작은 객체들을 공유)

프록시 (Proxy) : 실제 기능을 수행하는 객체 대신 가상의 객체를 사용해 로직의 흐름을 제어하는 패턴

3) 행위 패턴 (Behavioral Pattern)

객체나 클래스 사이의 알고리즘이나 책임 분배에 관련된 패턴으로, 한 객체가 혼자 수행할 수 없는 작업을 여러 개의 객체로 어떻게 분배하는지, 또 그렇게 하면서도 객체 사이의 결합도를 최소화하는 것에 중점을 둔다.

책임 연쇄 (Chain of Responsibility) : 객체들끼리 연결 고리를 만들어 내부적으로 전달하는 패턴

커맨드 (Command) : 요청 자체를 캡슐화하여 파라미터로 넘기는 패턴

인터프리터 (Interpreter) : 문법 규칙을 클래스로 표현하는 패턴

반복자 (Iterator) : 구현 방법을 노출하지 않으면서 모든 항목에 접근할 수 있는 방법을 제공하는 패턴

중재자 (Mediator) : 객체 간 상호작용을 캡슐화한 패턴

메멘토 (Memento) : 상태 값을 미리 저장해 두었다가 복구하는 패턴

옵저버 (Observer) : 객체 상태가 변할 때 관련 객체들이 그 변화를 전달받아 자동으로 갱신하는 패턴

상태 (State) : 객체의 상태에 따라 동일한 동작을 다르게 처리하는 패턴

전략 (Strategy) : 동일 계열의 알고리즘 군을 정의하고 캡슐화하여 상호 교환이 가능하게 하는 패턴

템플릿 메서드 (Template Meothods) : 상위 클래스는 알고리즘의 골격만을 작성하고 구체적인 처리는 서브 클래스로 위임하는 패턴

방문자 (Visitor) : 방문자 패턴은 방문자와 방문 공간을 분리하여 방문 공간이 방문자를 맞이할 때, 이후에 대한 행동을 방문자에게 위임하는 패턴

정리

이 패턴을 사용한다는 것은 어떤 의도를 전달하려는 건지, 그러기 위해 클래스 구조를 어떻게 설계할 수 있는지에 대해서 아는 것이다. 디자인 패턴은 결국 다른 개발자와 커뮤니케이션하기 위해 배우는 것

4. 자주 사용하는 디자인 패턴 종류

1) 싱글톤(Singleton)

• 인스턴트가 필요할 때, 똑같은 인스턴스를 만들지 않고 기존의 인스턴스를 활용함
• 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴

1️⃣ 싱글톤 장점

• 메모리
→ 최초 한번의 new 연산자를 통해서 고정된 메모리 영역을 사용하기 때문에 추후 해당 객체에 접근할 때 메모리 낭비를 방지할 수 있다.(객체들이 복제되는 경우를 방지)

• 속도
→ 이미 생성된 인스턴스를 활용하니 속도 측면에서도 이점이 있다고 볼 수 있다.

• 데이터 공유
→ 전역으로 사용되는 인스턴스이기 때문에 다른 클래스의 인스턴스들이 접근하여 사용할 수 있다.

• 데이터 공유
→ 싱글톤의 역할이 커질수록 결합도가 높아져 객체 지향 설계 원칙에 어긋날 수 있다.

2️⃣ 싱글톤 단점

• 코드양
→ 싱글톤 패턴을 구현하는 코드 자체가 많이 필요하다.

• 테스트
자원을 공유하고 있기 때문에 테스트가 격리된 환경에서 수행되려면 매번 인스턴스의 상태를 초기화시켜주어야 한다. (그렇지 않으면 어플리케이션 전역에서 상태를 공유하기 때문에 테스트가 온전하게 수행되지 못한다.)

3️⃣ 코드 예제

class SingletonTest {
  private static SingletonTest instance;
  private int value;
  
  // 외부에서 생성자를 통해 생성하는 것을 막음
  private SingletonTest(int value){
    this.value = value;
  }
  public SingletonTest getInstance(int value){
    if(instance === null) {
      instance = new SingletonTest(value);
    }
    return instance;
  }
}

2) 팩토리메서드(Factory Method)

: 객체를 생성하기 위해 인터페이스를 정의하지만, 어떤 클래스의 인스턴스를 생성할지에 대한 결정은 서브클래스가 내리도록 하는 패턴이다.(객체를 생성 반환하는 메서드)
객체를 만들어 반환하는 함수를 생성자 대신 팩토리 형태로 제공하여 초기화 과정을 외부에서 보지 못하게 숨기고 반환 타입을 제어하는 방법이다.

Factory Pattern이 나오게 된 이유?

객체 지향 디자인 패턴의 기본 원칙은 확장에 있어서는 열려 있어야 하며, 수정에 있어서는 닫혀 있어야 한다는 것이다. (OCP, Open Closed Principle)

코드를 수정하지 않아도 모듈의 기능을 확장하거나 변경 할 수 있어야 한다. 때문에, 수정이 일어날 가능성이 큰 부분과 그렇지 않은 부분을 분리하는 것이 좋다.

객체는 수정이 될 수 있으며, 이에 따라 객체의 생성을 담당하는 코드는 변경의 가능성이 높다. 그래서 객체의 생성을 담당하는 클래스를 한 곳에서 관리하여 결합도를 줄이기 위하여 팩토리 패턴이 나타나게 된 것이다.

결합도란?

class Troll () {
  init {}
}

class User {
  let a  = Troll()
}

// 여기서 User class는 Troll class에 의존 하고 있다.
// 만약 Troll class가 없어자면 User class는 컴파일이 안되며, 동작도 안함

위의 코드 예시와 같이, 결합도는 한 클래스에 변경점이 얼마나 다른 클래스에 영향을 주는가를 의미한다.

1️⃣ 사용하는 경우

• 어떤 클래스가 자신이 생성해야 하는 객체의 클래스를 예측할 수 없을 때
• 생성할 객체를 기술하는 책임을 자신의 서브클래스가 지정했으면 할 때

Creator - 객체를 생성하는 팩토리 메소드를 가진 인터페이스(API), Product클래스를 생성하는 클래스
Product - 팩토리 메서드로 생성될 객체의 공통 인터페이스, 구체적인 역할은 하위클래스인 ConcreteProduct이 결정함.
ConcreteProduct - 구체적으로 객체가 생성되는 클래스
ConcreteCreator - 팩토리 메서드를 구현하는 클래스로 ConcreteProduct 객체를 생성

예시
https://gdtbgl93.tistory.com/19

참고:
https://gmlwjd9405.github.io/2018/07/06/design-pattern.html
https://truehong.tistory.com/113
https://velog.io/@poiuyy0420/디자인-패턴-개념과-종류
https://dailyheumsi.tistory.com/218?category=855210
https://tecoble.techcourse.co.kr/post/2020-11-07-singleton/
https://velog.io/@ljo_0920/팩토리-메서드

profile
코딩으로 세상에 이야기하는 개발자

0개의 댓글