본문 바로가기

23년 2학기 학교공부/소프트웨어공학

[SE] 디자인 패턴

목차

    728x90
    반응형
    SMALL
    2023학년도 2학기 충남대학교 김현수 교수님의 소프트웨어공학 수업 정리자료입니다.

     

     

     

     

    📁 디자인 패턴

    디자인 패턴이란 자주 접하는 설계 문제를 해결해주는 증명된 솔루션을 체계적으로 정리한 것을 말한다.

    공통의 설계 목표를 만족시키는 클래스의 조합, 협력 알고리즘이다.

     

    여러번의 시행착오를 거치면서 비슷한 역할의 클래스를 자주 사용하게 되는데, 이를 모아서 목록화한게 무?

     

    전문가의 노하우를 모아놓은 것이므로 이를 적용하면 좋은 설계가 되도록 도와준다. 코드를 더 견고하게 한다던가, 재사용을 용이하게 한다.

     

     

    디자인 패턴은 크게 기본 패턴, 생성 패턴, 구조 패턴, 행위 패턴으로 나눌 수 있다.

     

     

     

     

     

    🌱 기본 패턴

    객체지향 패턴의 관용구로, 흔히 쓰이는 패턴이다.

     

    개념실체 패턴, 플레이어 역할 패턴, 위임 패턴, 계층 구조 패턴 등이 있다.

     

     

    1. 개념실체 패턴(abstraction occurrence)

    각 객체의 공통 정보를 공유할 때 사용한다.

    여기서 개념이란 공유하는 정보를 담고 있는 클래스를 말하고, 실체란 공통된 정보를 가진 멤버를 말한다.

    예를 들면 아래 다이어그램에서 Insuarance와 BookTitle이 개념 클래스, Policy와 LibraryItem이 실체클래스이다.

     

    이렇게 개념클래스와 실체클래스를 분리하는 이유는 중복되는 정보를 저장하지 않기 위함이다.

     

     

     

     

    2. 플레이어 역할(player role) 패턴

    하나의 클래스에 다양한 역할을 표현하고 싶을 때 사용한다.

    즉 플레이어가 환경에 따라 다른 역할을 해야하는 경우를 말한다.

     

    플레이어 역할 패턴을 생성하는 방법은 여러가지 다른 역할을 하는 Player를 생성한 후, 이를 각 역할의 집합에 대한 수퍼클래스와 연관관계를 형성한다.

    예를 들어 "학생" 플레이어는 어떤 수준의 공부를 하냐에 따라 학부생 혹은 대학원생 역할을 맡을 수 있고, 수업 수강 방식에 따라 풀타임학생 혹은 파트타임 학생일 수 있다. 이때 풀타임학생과 파트타임 학생 역할 클래스를 생성한 후, 이를 AttendanceRole이라는 수퍼클래스를 생성하여 연관관계를 맺을 수 있다.

     

     

     

     

    3. 위임(delegation) 패턴

    다른 클래스가 가진 특정 오퍼레이션에 작업을 요청하여 책임을 위임할 때 사용한다.

    위임받는 클래스와 연관관계가 필수이다.

     

    위임 패턴은 아래와 같은 원리를 제공한다.

    상속보다 연관을 통해 효과적으로 재사용이 가능하다. 상속은 불필요한 변수나 오퍼레이션도 함께 상속될 수 있다는 단점이 있다.

    코드 중복을 피할 수 있다.

    연관으로 근접한 정보에만 접근한다.

     

     

     

     

    4. 계층 구조 패턴

    계층 관계를 가진 객체들을 묶어 동일한 처리를 하고 싶을 때 사용한다.

    보통 회사의 조직도, 파일 구조, 구문 트리 등 계층 구조를 다룰 때 적용한다.

     

     

     

     

     

    🌱 생성 패턴

    간단한 블록의 코드로 여러가지 다양한 객체를 생성한다.

    실행시간에 객체의 다양한 버전을 생성하고, 클래스 인스턴스 생성을 하나로 제한하는 등 생성한 객체에 제한을 가한다.

     

    팩토리 패턴, 추상 팩토리 패턴, 프로토타입 패턴, 싱글톤 패턴 등이 있다.

     

     

     

     

    1. 팩토리(factory) 패턴

    객체를 생성하기 위해 먼저 인터페이스를 정의하고, 어떤 클래스의 인스턴스를 생성할지에 대한 결정은 서브클래스에서 이루어지도록 생성의 책임을 미룬다. 즉 클래스 인스턴스를 다양한 형태의 객체로 반환한다.

    객체를 생성하는 코드는 클래스와 메소드로 분리한다. 그러면 객체 생성 방식의 변화에 대비하는데 유용하다.

     

    팩토리패턴을 사용하는 이유는 베이스 클래스에 속하는 객체 중 하나가 필요하거나, 자식 객체 중 어떤 것이 필요한지 실행 시간까지 알 수 없는 경우에 사용한다.

     

    팩토리 패턴을 사용한 예시는 다음과 같은 경우가 있다.

     

     

     

     

    2. 추상 팩토리(abstract factory) 패턴

    객체의 구체적인 클래스를 명시하지 않고서 그 객체와 연관되는 객체 그룹을 생성하는 인터페이스를 제공한다.

    객체 그룹을 생성하거나 의존적인 관계의 객체를 생성할 때 객체 생성을 추상화한다. 이러한 추상화를 통해 객체를 사용하는 모듈은 객체와 독립적으로 행동한다.

     

    팩토리 패턴과의 차이점은 팩토리 패턴의 개념을 사용하지만, 객체 그룹의 생성을 의존관계에 있는 객체 무리에 적용함으로써 추상화하고, 스타일에 따라 다른 객체 그룹을 생성한다는 점이 있다.

     

    객체 그룹 생성을 추상화하는 추상 팩토리 패턴의 예시는 다음과 같은 경우가 있다.

     

     

     

     

    3. 프로토타입(prototype) 패턴

    객체를 사용할 때 다시 생성하지 않고 복사(clone)해서 사용한다.

    클래스로부터 인스턴스를 생성하지 않고 이미 생성된 인스턴스로부터 새로운 인스턴스를 생성한다. 그리고 새로운 인스턴스가 필요할때마다 프로토타입의 클론(복사본)을 생성한다.

    객체를 생성하기 위해 원격 데이터를 여러번 접근해야하거나, 객체 생성을 위해 필요한 정보를 일일이 기입해야하는 경우에 사용한다.

     

    클론 메소드란 일반 데이터를 매개변수로 넘겨주면 원하는 형태의 객체를 생성해준다.

    복제 후 간단히 변환하는 방식으로 조금씩 다른 객체들을 생성한다.

     

    프로토타입 패턴 사례로 다음과 같은 Ensemble 객체 사례가 있다.

    myPartPrototype이라는 이름으로 MyPart 객체를 모으고 있다.

     

     

     

     

    4. 싱글톤(singleton) 패턴

    어떤 클래스 S의 인스턴스를 하나만 만들고자 할 때, 혹은 어플리케이션 전체에 하나만 필요한 경우에 사용된다.

     

    예를 들면 시스템 로그 파일이나, 라이브러리 카탈로그 등은 어플리케이션 전체에 단 하나만 필요하다.

     

    싱글톤 패턴의 핵심은 오직 한 개의 객체만 존재하게 하려는 목적때문에 더 잇아의 인스턴스를 생성하지 못하도록 생성자의 호출을 안전하게 막아야한다. 이를 위해서 S라는 클래스가 있을 때, S의 생성자를 private으로 만들고, S 안에 private 정적 속성을 정의한 후 이를 접근하는 public 함수를 제공하는 방식으로 동작한다.

     

     

     

     

     

    🌱 구조 패턴

    더 큰 구조를 형성하기 위해, 클래스와 객체는 인터페이스를 상속받아 구현하는 방식으로 합성된다.

     

    구조패턴은 새로운 기능을 구현하기 위해 객체를 구성하고, 런타임에 객체 구조를 변경하여 유연성, 확장성을 높인다.

     

    컴포지트 패턴, 데코레이터 패턴, 어댑터 패턴, 퍼싸드 패턴, 프록시 패턴 등이 있다.

     

     

     

     

    1. 컴포지트(composite) 패턴

    객체의 트리를 나타내는데 사용한다.

     

    기본 클래스와 이를 포함하는 컨테이너 클래스를 재귀적인 형태로 표현하는 패턴이다. 예를 들어 디렉토리 내에 디렉토리와 파일이 있는 구성과 같다.

     

    객체들의 집합을 다룰 때 유용하며, 그 이유는 다음과 같다.

    집합 속에 포함될 객체와 집합을 가지고있는 객체 모두가 자기자신과 동일한 메소드와 데이터를 가질 수 있게 한다.

    객체 집단을 삽입하거나 삭제하기가 용이하다.

    특정 객체 집단에 명령을 전달하면 객체 집단 모두가 그 명령을 수행한다.

     

     

     

     

    2. 데코레이터(decorator) 패턴

    런 타임에 객체의 기능을 추가하기 위해 사용한다.

     

    객체 생성 없이 개별 객체에 데코레이터를 이용하여 동작을 첨부할 수 있다.

     

    추가적인 동작을 첨부하기 위해서는 대상 객체를 원하는 기능을 가지고 있는 데코레이터에 파라미터로 전달하는 방식을 사용한다.

    Decoration decoration1 = new Decoration(aSubstance);

     

     

     

    데코레이터 패턴을 사용하는 사례로 GUI 설계가 있다.

    GUI를 설계할 때 상속을 이용하면 융통성이 없어진다. 이를 해결하기 위해 화면 구성 클래스와 추가기능
    (decorater)를 분리한 후, 하나의 화면 구성 클래스에 여러개의 기능들이 연결되도록 구성한다.

     

    new BorderDecorator(new ScrollDecorator(new TextView()));

     

     

     

     

    3. 어댑터(adapter) 패턴

    어플리케이션의 기능을 외부에서 필요한 형태로 수정하여 쓰기 위해 사용한다.

     

    원하는 인터페이스를 추상 클래스로 정의한 후, 이를 상속하는 어댑터 클래스를 만들고 이를 요구하는 기능을 가진 클래스(adaptee)와 메세지를 교환하는 방식으로 동작한다.

     

    기존에 존재하는 클래스를 재사용하고 싶지만 원하는 인터페이스와 맞지 않는 경우, 혹은 미리 정해져있지 않은 클래스들과 상호작용할 수 있는 재사용 가능한 클래스를 만들고자 할때 사용하는 패턴이다.

     

     

    어댑터 패턴을 이용하는 사례로 다음과 같은 경우가 있다.

     

     

     

     

    4. 퍼싸드(facade) 패턴

    시스템을 구성하는 많은 기능들의 '간단한 입구' 역할을 제공한다.

     

    클라이언트 프로그램이 사용하려는 패키지 안에 포함된 여러개의 클래스 중에서 특정 클래스를 인터페이스로 정의한다.

    외부에서 호출한 기능을 내부의 다른 클래스에 위임 형태로 전달한다.

    외부 클라이언트에게는 내부의 복잡한 내용을 감춘다.

    패키지가 변경될 경우 다른 패키지의 클래스가 아닌 <<Facade>> 클래스의 재설계만 필요하다.

     

    facade란 프랑스어로 건물의 정면 혹은 대문이라는 뜻이ㅏ.

    위 경우 Airline이라는 Facade 클래스가 있다.

    클라이언트는 Airline 클래스의 findFlight() 함수를 실행하기만 하면 되고, 비행기를 찾기 위한 모든 과정은 Airrline 클래스 내부의 findFlight() 함수가 정의한다. 즉 패키지클래스들 중 하나가 변경되더라도 client는 변경 없이 그대로 findFlight() 함수를 사용하고 있으면 되고, Airline 클래스 내부에서 재설계를 수행한다.

     

     

     

     

    5. 프록시(proxy) 패턴

    복잡하거나 생성하는데 시간이 오래 걸리는 객체를 좀 더 간단한 객체로 표현하여 그 객체가 필요할 때까지 생성을 지연시킨다.

     

    특정 객체에 접근을 조절하기 위해 대리자(프록시)를 세운다. 이후 필요할 때만 비싼 대가의 기능에 접근한다.

     

    로딩하는데 시간이 많이 소요되는 큰 그림과 같은 객체를 사용할 때나, 네트워크 작업에서 트래픽이 증가하여 객체의 로딩이 느릴때나, 사용자에게 권한이 제한된 객체로의 접근을 허용하게 하는 경우에 사용한다.

     

     

    프록시 패턴은 다음과 같이 호출한다.

     

     

    프록시 패턴의 사례로 이미지 대신 심볼을 간단하게 디스플레이하는 경우가 있다.

     

     

     

     

     

    🌱 행위 패턴

    객체 사이의 행위를 조직화하고 연합하는데 사용하는 패턴을 말한다.

    객체나 클래스의 유형을 정의하는게 아니라, 클래스 사이의 책임과 협력에 대한 유형을 제시한다.

    객체들 간의 기능을 배분하거나 연동을 프로토콜화 하는 목적이다.

     

    옵서버 패턴, 중재자 패턴, 책임 체인 패턴, 커맨드 패턴, 상태 패턴 등이 있다.

     

     

     

     

    1. 옵서버(observer) 패턴

    정보 제공자와 이용자 사이의 연관을 관리하는 패턴을 말한다.

    정보를 제공하는 객체의 변화가 이용 객체제 전달되어야 하는 경우에 사용한다.

     

    특정 데이터나 객체를 감시하다가, 변화가 발생하면 이를 알리고 연관된 객체들이 적절한 작업을 수행한다.

     

    단일 객체가 영향받는 객체 집합에 대해 같은 이름의 메소드를 호출하여 구현한다.

    관찰 대상 객체는 관찰하는 객체가 몇개인지, 어떤 클래스인지에 대한 구체적인 정보를 모른다.

     

     

    1) ConcreteObservable 클래스 : 상태 변화 발생 및 자신의 상태 변화를 저장한다.

    상태가 변경되어 이를 전달하고자 할 때 Observable 클래스의 notifyObservers()를 호출한다.

     

    2) Observable 클래스 : 상태 변화를 통보할 때 Observer 인터페이스를 통해 ConcreteObserver 객체 안의 update()를 호출한다.

     

    3) ConcreteObserver 클래스 : update() 메소드 안에서 ConcreteObservable 객체 상태를 받아서 그래프를 그리거나 변경된 상태를 이용해 다른 작업을 수행한다.

     

     

     

     

    2. 중재자(mediator) 패턴

    관련된 객체 사이에 레퍼런스를 피하고자 할 경우에 사용한다.

    중재자 객체가 중간에서 객체 간의 변화나 메세지를 조정한다.

     

    여러 객체가 서로 메세지를 주고받는 협력 행위를 특정 객체 안에 캡슐화한다.

    다른 객체의 존재를 모르는 상태에서도 메세지를 주고받을 수 있다.

    특정 객체를 수정하지 않고도 협력 행위만 쉽게 변경할 수 있다.

    – Mediator • Colleague 객체들과 의사 소통에 필요한 인터페이스를 정의 – ConcreteMediator • Colleague 객체들을 포함, 그들 간의 상호작용을 조정하여 협동 작업을 실현 – Colleague classes • Mediator 객체를 알고 있고 Mediator 객체를 통해서만 상호작용을 수행

     

    중재자 패턴에서 두 초기화 작업의 시퀀스 다이어그램은 다음과 같다.

     

    중재자 패턴의 사례로 고객 정보 입력 GUI가 있다.

    – 다이얼로그 박스(Basic Info.)는 리스트 박스와 입력 폼을 포함 – 왼쪽 리스트 박스에서 고객 타 입 지정 – 지정된 고객 타입에 따라 오른 쪽 입력 폼 형태가 바뀜

    • 두 컴포넌트 간에 직접적인 의 존 관계 발생하지 않음 • 컴포넌트의 재사용성 증진 – 직접 레퍼런스는 재사용을 어 렵게 함

     

     

     

     

    3. 책임 체인(chain of responsibility) 패턴

    사용자가 원하는 작업을 어떤 객체에게 맡길지 모를 때 그 작업을 다 룰만한 객체들의 집합에 맡긴다.

     

    작업을 수행하는 객체를 체인처럼 엮어 놓았다가 외부의 요청이 있 으면 이를 체인에 넘긴다.

    객체의 체인은 넘어온 요청을 확인한 후 이를 처리할 수 있는 객체에 게 작업을 수행하게 한다.

     

    메시지를 보내는 객체가 메시지를 받는 모든 객체를 다 알 필요가 없 음 (메시지를 받을 단 하나의 객체만 알면 됨) – 요구 요청 객체와 처리 객체 사이를 느슨하게 연결

     

    handlersubclassA, B, C..가 체인 형태로 연결되어 있어서, client가 handlersubclassA에게 요청한 이후 A가 할수있는 일을 모두 하면 남은 일을 B에게 넘기고, 이런식이다.

     

     

     

     

    4. 커맨드(command) 패턴

     

     

     

    5. 상태(state) 패턴

     

     

     

    더보기

    참고

    https://velog.io/@bagt/Design-Pattern-Facade-Pattern-%ED%8D%BC%EC%82%AC%EB%93%9C-%ED%8C%A8%ED%84%B4

     

    [Design Pattern] Facade Pattern (퍼사드 패턴)

    퍼사드 패턴(Facade Pattern)은 구조 패턴(Structural Pattern)의 한 종류로써, 복잡한 서브 클래스들의 공통적인 기능을 정의하는 상위 수준의 인터페이스를 제공하는 패턴이다.퍼사드 객체(Facade Object)는

    velog.io

    https://velog.io/@wlsrhkd4023/Design-Pattern-%EC%A4%91%EC%9E%AC%EC%9E%90-%ED%8C%A8%ED%84%B4Mediator-Pattern

     

    [Design Pattern] 중재자 패턴(Mediator Pattern)

    중재자 패턴(Mediator Pattern)은 객체간의 상호작용을 캡슐화하는 디자인 패턴으로 프로그램의 실행중 행위를 바꾸는 방법으로 Behavior Pattern에 속하게됩니다. 객체 지향 프로그래밍에서 프로그램은

    velog.io

    https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-Chain-Of-Responsibility-%ED%8C%A8%ED%84%B4-%EC%99%84%EB%B2%BD-%EB%A7%88%EC%8A%A4%ED%84%B0%ED%95%98%EA%B8%B0

     

    💠 Chain Of Responsibility 패턴 - 완벽 마스터하기

    Chain Of Responsibility Pattern 책임 연쇄 패턴(Chain Of Responsibility Pattern, COR)은 클라이어트의 요청에 대한 세세한 처리를 하나의 객체가 몽땅 하는 것이 아닌, 여러개의 처리 객체들로 나누고, 이들을 사

    inpa.tistory.com

    https://gmlwjd9405.github.io/2018/07/07/command-pattern.html

     

    [Design Pattern] 커맨드 패턴이란 - Heee's Development Blog

    Step by step goes a long way.

    gmlwjd9405.github.io

    https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EC%83%81%ED%83%9CState-%ED%8C%A8%ED%84%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EC%9E%90

     

    💠 상태(State) 패턴 - 완벽 마스터하기

    State Pattern 상태 패턴(State Pattern)은 객체가 특정 상태에 따라 행위를 달리하는 상황에서, 상태를 조건문으로 검사해서 행위를 달리하는 것이 아닌, 상태를 객체화 하여 상태가 행동을 할 수 있도

    inpa.tistory.com

     

    728x90
    반응형
    LIST