언리얼 프로젝트를 진행하며, 느슨한 결합을 유지하기위해 델리게이트를 사용하게 되었습니다.

델리게이트를 사용 하던 중, 델리게이트는 기존에 학습하였던 옵저버 패턴(Observer Pattern)을 사용한 것 같다고 느껴졌습니다.

이를 기반으로 옵저버패턴의 정의와 특징 그리고 게임 클라이언트 환경에서 옵저버 패턴을 적용한 경우들에 대해 알아보겠습니다.

※ 델리게이트 (Delegate) - https://mynameiskgws.tistory.com/16

 

https://ko.wikipedia.org/wiki/%EC%98%B5%EC%84%9C%EB%B2%84_%ED%8C%A8%ED%84%B4

옵저버/감시자 패턴 (Observer Pattern) 정의 / 특징

  • 관찰자(Observer)들이 관찰하고 있는 대상자(Subject)의 상태가 변경시에 대상자는 각 관찰자들에게 알림(Eventg)을 전달, 관찰자는 알림을 수신받아 변화에 대한 조치를 취하는 행동
    • 통보를 받은 관찰자가 값을 변경, 삭제, 알림 등 대응을 한다.
  • 1:N의 의존성을 가지며, 분산 이벤트 핸들링 시스템을 구현하는데 사용한다.
    • 한개의 대상자 (Subject) :  관찰자 (Observer A,B,C...)
  • 관찰 대상자(Subject) 인터페이스와 관찰자(Observer) 클래스로 구분되어 사용한다.
  • Observer들은 Subject의 그룹에서 추가/삭제가 동적으로 이루어진다.
  • 한 객체의 상태가 변경되면 다른 객체도 변경해야 할 때, 변경되는 다른 객체들이 변경되어야 하는지 몰라도 될 때

 

장점

  • 대상자의 상태 변경을 주기적으로 조회하지 않고 자동으로 감지할 수 있다.
  • Observer클래스를 추가/삭제 시 Subject의 코드를 변경하지 않기 때문에 OCP원칙을 준수하며, 느슨한 결합성을 유지한다.
  • 런타임 시점에 관계를 맺는다.
    • 프로그램 코드가 상호작용되어야하는지 확인할 때 정적으로 알 수 없으며, 명령 실행과정을 동적으로 추론해야하기 때문에 단점 일 수 있다.

단점

  • 동기적(Syncronized)이다.
    • Observer중 하나라도 느릴 경우, 대상이 블록 될 수 있다.
  • Observer를 멀티스레드, 락과 함께 사용시에는 교착상태에 빠질 수 있다.
    • 이벤트 큐를 사용하여 비동기적으로 상호작용하여 안정적으로 처리할 수 있다.
  • 알림 순서를 제어할 수 없다. 즉, 무작위 순서로 알림을 받는다.
  • 옵저버 객체를 등록 후 해지하지 않는다면, 메모리 누수가 발생할 수 있다.

 

사용 예시

  • 델리게이트(Delegate)를 사용하여 캐릭터의 체력이 변경될 경우 UI에 자동으로 반영
    • Subject : PlayerCharacter
    • Observer : UI
    • Event(Delegate) : DelegateSingature
  • 게임의 업적 기능
  • Java의 라이브러리 (java.util.Observer), C#의 Event
  • 유튜브 (채널 : Subject / 구독자 : Observer)
  • MVC패턴 (Model : Subject / View: Observer)

출처 및 참고내역

https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EC%98%B5%EC%A0%80%EB%B2%84Observer-%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 

 

도서 - 게임 프로그래밍 패턴

 

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

[디자인패턴] - MVC, MVVM 패턴  (1) 2025.02.18
[디자인패턴] - 프록시 패턴 (Proxy Pattern)  (0) 2025.02.07
Factory Method Pattern  (0) 2024.12.24
Command Pattern  (2) 2024.12.23
디자인 패턴의 정의 및 종류  (0) 2024.12.05

기존에 스프링 프레임워크를 사용한 백엔드 프로젝트를 제작시 스프링 프레임워크에는 MVC패턴을 기반으로 설계되어있다. 라고 학습한 경험이 있습니다.

현재 언리얼 엔진을 사용한 게임 클라이언트 관련 프로젝트를 진행하며 디자인 패턴 및 아키텍처 설계에 대해 고민하게 되었으며, 언리얼에서도 학습했던 MVC 패턴을 적용 할 수 있을지에 대해 고민하던 중, 다시 리마인드하며 학습한 MVC,MVVM패턴에 대해 작성하겠습니다.

 

MVC (Model - View - Controller) 패턴

출처 - https://www.freecodecamp.org/news/the-model-view-controller-pattern-mvc-architecture-and-frameworks-explained/

 

정의

소프트웨어 아키텍처 설계시 사용 할 수 있는 디자인 패턴 중 하나입니다.

어플리케이션을 모델(Model), 뷰 (View), 컨트롤러(Controller)로 분리하여 관심사를 분리하며 유지보수성 및 확장성을 높이는 구조입니다.

UI기반의 어플리케이션 계층에서 자주 사용되는 패턴 중 하나입니다.

 

모델 (Model)

  • 어플리케이션의 데이터 및 비즈니스 로직을 관리하는 부분
  • 데이터베이스와 연동되거나, 내부적으로 데이터 처리, 유효성검사와같은 작업을 수행한다.
  • 독립적으로 작동하며 뷰와 컨트롤러와 직접적으로 통신하지 않는다.
  • 언리얼에서의 Model : 캐릭터 Info 관련 Property, 스킬, GameState및 GameInstance를 사용한 게임 상태 관리

 

뷰 (View)

  • 유저에게 화면을 표시하는 역할
  • 모델에서 받은 데이터를 시각적으로 표현한다.
    • Model과 직접적으로 통신하는것이 아닌, Controller에 의해서 받아온다.
  • 사용자의 입력을 받아 컨트롤러에 전달한다.
  • UI (체력 바, 미니맵, 스코어 표시 등)

 

컨트롤러 (Controller)

  • 사용자의 입력을 처리하며, 어플리케이션의 전체적인 흐름을 관리
  • 뷰에서 전달한 사용자의 입력을 분석, 입력에 맞는 모델의 데이터를 변경, 뷰 최신화
  • 키보드 입력과 같은 Input Action
  • UI 버튼(뷰) 클릭 시 특정 기능 수행

 

MVC 패턴 장단점

  • M-V-C 각각의 역할을 명확하게 구분하여 결합도가 낮다. 확장성이 높다.
  • 모델은 독립적이며, 다른 View에서도 재사용이 가능하다. 재사용성이 높다.
  • M-V-C 각각의 역할이 분리되어있어 코드 충돌을 방지하기 쉽다.
  • 작은 프로젝트에서는 오히려 코드가 많아지고, 복잡도가 증가할 수 있다.
  • M-V가 직접 연결되지 않는 설계가 필요하다.
  • 모델 변경시 뷰가 자동 갱신되지 않으면 추가적인 데이터 바인딩이 필요할 수 있다.

 

 

 

 

 

MVVM (Model - View - ViewModel) 패턴

출처 - https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%EB%B7%B0%EB%AA%A8%EB%8D%B8

 

정의

MVVM(Model-View-ViewModel) 패턴은 MVC패턴과 같은 아키텍처 패턴 중 하나로, MVC패턴에서 확장된 패턴입니다.

Controller 대신 ViewModel이 사용되었으며, 뷰 모델이 모델에 있는 데이터 객체를 노출하는 책임을 지기때문에 객체를 관리하고, 표현하기 위해 확장되었습니다.

 

 

Model(모델)

  • MVC패턴과 같은 역할을 한다.
  • 데이터 처리, 로직, 유효성 검사 등
  • HP,Level,Skill 등

 

View(뷰)

  • 사용자가 화면에서 보는것들에 대한 구조, 배치, 외관 등 시각적 요소
  • ViewModel과 데이터 바인딩을 통해 데이터를 표시한다.
  • 체력 바, 점수, 미니맵 등

 

ViewModel(뷰 모델)

  • Model과 View 사이의 중개 역할
  • Model에서 데이터를 가져와 View가 이해할 수 있는 형태로 변환
  • 데이터 바인딩을 사용한 View와 자동 동기화
  • Model int32 HP -> View UTextBlock HP:100 표시 등

 

MVVM 패턴 장단점

  • ViewModel 활용한 UI(View) ,Model간 데이터 자동 동기화
  • UI와 비즈니스 로직을 분리할 수 있다.
  • ViewModel이 중개자 역할을 하며 로직을 처리하므로 각각의 역할이 분리된다.
  • UI를 변경해도 수정사항이 없다. 서로 관심사를 분리하여 유지보수성 및 확장성이 높다.
  • 데이터 바인딩을 하는 추가작업 필요 및 바인딩으로 인한 메모리 소모가 크다.

출처 및 참고내역

 

https://www.freecodecamp.org/news/the-model-view-controller-pattern-mvc-architecture-and-frameworks-explained/

https://dev.epicgames.com/community/learning/tutorials/eBqE/unreal-engine-programacion-con-mvvm-en-umg-interfaces-de-usuario 

D

 

 

프록시 패턴 (Proxy Pattern)

프록시 패턴은 대상 원본 객체에 대한 접근을 제어하기 위해 대리 객체를 제공하는 디자인 패턴입니다.

대상 원본 객체를 대리하여 대신 처리하게 함으로써 로직의 흐름 제어 및 추가적인 로직을 처리 한 뒤 접근 할 수 있습니다.

 

※ GoF 디자인 패턴에서는 접근 제어를 목적으로 구현한 경우 프록시 패턴,

※ 새로운 기능 추가(로깅, 데이터 검증 등)가 목적인 경우 데코레이터 패턴으로 분류합니다.

 

프록시 패턴 - https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9D%EC%8B%9C_%ED%8C%A8%ED%84%B4

 

프록시 정의 및 특징

  • Client -> Server 호출시 직접호출 하는것이 아닌, 어떠한 대리자를 통해서 간접적으로 Server에 요청하는 것
    • Client -> Proxy -> Server
    • 간접 호출하는 대상을 프록시 라고 한다.
  • 권한에 따른 접근 차단, 캐싱, 지연 로딩을 수행하는 접근제어
    • bool Access를 통한 접근제어
    • 인스턴스 하려는 객체가 너무 크거나 메모리를 많이 차지하는 경우 필요할 때만 객체를 생성하여 성능 최적화
  • 기존 객체에서 다른 기능까지 추가해주는 부가기능 추가
    • 데이터 유효성 검사(Data Validation) / 로깅(Logiing) 등
  • 원격 위치에 있는 객체를 가져와 로컬처럼 보이게 하는 원격 프록시
    • UE의 네트워크 리플리케이션 RPC는 프록시 기반으로 구현되어 있다.

 

 

프록시 패턴 구조

  • Subject : 프록시와 대상 객체를 하나로 묶는 인터페이스
    • 대상 객체와 프록시 역할을 동일하게 해주는 virtual 함수 DoAction() 정의
    • 인터페이스를 통해 클라이언트는 객체 호출시에도 다형성을 통해 ISubject를 호출하면 된다.
  • RealSubject : 원본 대상 객체
  • Client : ISubject를 상속한 프록시 객체를 생성해 호출
    • 클라이언트는 실제 객체 사이에 프록시를 두어 RealSubject와 데이터를 주고받는다.
  • Proxy : 대상 객체를 중계할 대리자 역할.
    • 대상 객체를 합성한다.
    • 가상함수 DoAction()을 호출하여 RealSubject의 DoAction()외 부가적인 로직을 수행 할 수 있다.
    • 흐름 제어를 하며, 결과 값을 조작하거나 변경시키지 않는다.

 

프록시 패턴 종류

가상 프록시 (Virtual Proxy)

 

원격 프록시 (Remote Proxy)

  • 프록시 클래스는 로컬에 있으며, 대상 객체는 원격 서버에 존재하는 경우
    • 언리얼의 리플리케이션(Replication) 시스템은 서버/클라이언트 간 프록시 객체를 사용한 원격 객체 대리 실행
    • https://mynameiskgws.tistory.com/38
  // Replication  
  // Server : 서버에서 실행되어야 하는 함수. 클라이언트에서 호출되더라도 자동으로 서버에서 실행
  // Client : 서버가 클라이언트에게 정보 전송시.
  // Reliable : 손실시 패킷을 재전송하여 데이터 손실 방지
  // WithValidation : 서버에서 요청을 받기 전에 유효성 검사를 한다. (프록시 특징인 부가기능. 데이터 유효성 검사)
  UFUNCTION(Server, Reliable, WithValidation)
  void Server_Func();
  
  
  void AActor::Server_Func_Implementation()
  {
    // 실제 서버에서 실행되는 로직
    // ...
  }
  
  bool AActor::Server_Func_Validation()
  {
    // WithValidation 사용시
    // 프록시 패턴을 통해 전송되는 로직에 대한 추가기능(데이터 유효성 검사) 에 대한 로직...
    return true/false;
  }

 

보호 프록시 (Protection Proxy)

  • 프록시가 대상 객체에 대한 자원으로의 액세스 제어 (접근 제한)
    • WithValidation을 사용하여 Func에 대한 로직 실행 전, Validation 함수를 통한 접근 제한
    • 엔진 내부적으로 IsServer, Server_Func_Validate()에 대한 조건이 true인 경우 동작하도록 구현되어 있다.
  • 특정 클라이언트만 서비스 객체를 사용할 수 있도록 하는 경우 
    • Ex) 특정 액터/UI에 대한 접근권한을 특정 플레이어에만 조작하도록 제한하는 경우

 

 

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

[디자인 패턴] 옵저버 패턴 (Observer Pattern)  (0) 2025.02.28
[디자인패턴] - MVC, MVVM 패턴  (1) 2025.02.18
Factory Method Pattern  (0) 2024.12.24
Command Pattern  (2) 2024.12.23
디자인 패턴의 정의 및 종류  (0) 2024.12.05

내일배움캠프를 통한 C++ 학습 과정 중 인터페이스를 사용한 다형성 및 캡슐화를 다루는 미니과제가 있었습니다.

 

UML 클래스 다이어그램 과정은 이렇습니다.

 

해당 다이어그램에서 인터페이스 Animal을 상속받는 Dog,Cat,Cow 클래스와,

Animal 객체들을 생성, 메서드 호출을 담당하는 Zoo클래스가 있습니다.

 

해당 다이어그램을 보았을 때 Zoo::addAnimal 메서드의 매개변수들을 전달하기 위해서는 Main 클래스에서 

Animal의 구현클래스들을 선언하는 구조가 되어있었습니다.

다형성 및 캡슐화를 중점으로 다루는 해당 과제에서 어떤 디자인 패턴이 어울리는지 찾아보던 도중, 팩토리 메서드 패턴을 적용하여 매개변수를 전달하는것이 가장 어울리는 것 같아 팩토리 메서드 패턴에 대한 포스팅을 하게 되었습니다.

 

이번 포스팅에서는 팩토리 메서드 패턴의 정의 및 특징, 그리고 장단점에 대해 알아보겠습니다.

 

Factory Method Pattern(팩토리 메서드 패턴)

  • 객체 생성을 공장(Factory) 클래스로 캡슐화 처리하여 대신 생성하게 하는 생성 디자인 패턴
  • 새로운 제품(클래스)를 추가 시에도 서브클래스만 추가하면 된다. -> 유지보수성 및 유연성이 높다.
  • 구체적인 클래스에 의존하지 않아 결합도를 낮추고 확장성을 높일 수 있다.

 

장점 및 단점

  • 기존의 코드에 영향을 미치지 않으면서, 새로운 서브 클래스만 추가하면 된다.
  • 객체 생성에 대한 세부사항을 캡슐화 하여 유지보수성을 향상시킨다.
  • 객체 생성 방식이 변경되어도 클라이언트는 영향을 받지 않는다.
  • 객체 생성이 여러 단계의 추상화로 이루어지기때문에, 불필요한 복잡성이 높아질 수 있다.

 

사용 예시

해당 사용 예시는 미니 과제를 중점으로 제작하였으며, Simple Factory Pattern으로 구현되었습니다.

해당 사유는 미니 과제를 중점이며 동시에 캡슐화를 사용한 정보은닉을 목적으로 하며 동시에 직관적으로 표현하기 위해서입니다.

팩토리 메서드 패턴으로 변형을 하려면 createAnimal 메서드를 추상화 하여 하위 클래스에서 구현 및 각 Animal 클래스들의 생성부분을 구현해야합니다.

 

Factory

Factory에서는 클라이언트에서 AnimalType을 매개변수로 받아 그에 맞는 객체 생성을 담당합니다.

class AnimalFactory
{
public:
	static Animal* createAnimal(const AnimalType& type);
};
Animal* AnimalFactory::createAnimal(const AnimalType& type)
{
	switch (type)
	{
	case DOG:
		return new Dog;
		break;
	case CAT:
		return new Cat;
		break;
	case COW:
		return new Cow;
		break;
	default:
		throw std::invalid_argument("AnimalType Eroor");
		break;
	}
}

 

Client

	// 재사용성 고려 보다는 협업 시 명확한 의도를 전달하기 위해 열거형을 사용했습니다.
	switch (randNum)
	{
	case DOG:
		return AnimalFactory::createAnimal(AnimalType::DOG);
		break;
	case CAT:
		return AnimalFactory::createAnimal(AnimalType::CAT);
		break;
	case COW:
		return AnimalFactory::createAnimal(AnimalType::COW);
		break;
	default:
		break;
	}

 

팩토리클래스의 createAnimal는 전역 함수이기때문에 해당 팩토리의 객체를 생성하지않고 호출할 수 있게 구현하였습니다.

 

 

정리

  • 객체 생성을 Factory 클래스로 캡슐화 처리하여 해당 객체를 대신 생성하는 디자인 패턴.
  • 객체 생성에 대한 세부사항을 캡슐화하여 유지보수성 향상 및 정보은닉성을 향상시킨다.
  • 기존의 코드에 영향을 미치지 않으며, 수정시 새로운 서브클래스만 추가하면 된다.
  • 하나의 Factory에서 생성을 담당한다 - Simple Factory Pattern
  • 상위 Factory 클래스를 인터페이스화, 하위 클래스에서 구현한다 - Factory Method Pattern

지난 포스팅에서 디자인패턴의 정의 및 특징을 비롯한 디자인패턴 종류들에 대해 알아보았습니다.

디자인패턴 정의 및 종류

 

이번 포스팅에서는 게임 클라이언트 개발 시 자주 사용하는 디자인 패턴중 하나인 커맨드 패턴에 대해서 알아보겠습니다.

 

커맨드 패턴

  • 요청 자체를 캡슐화 하는패턴으로, 서로 다른 사용자 (Ivoker-Receiver)를 매개변수로 만들고, 요청을 대기시키거나 로깅하며 되돌릴 수 있는 연산을 지원한다.
  • 어떤 행동을 나타내는 객체를 변수에 할당(캡슐화)하여 유동적으로 교체 할 수 있게 한다.
  • 행동 패턴(Behavioral Patterns)중 하나.
    • 객체나 클래스 사이의 알고리즘 혹은 책임 분배에 관련된 패턴이다.
    • 객체 사이의 결합도를 최소화 하는것에 중점을 가지고 있다.

 

장점 및 단점

  • 호출시 Invoker 객체에서 실행만 하는 구조로 설계되어 클래스간의 책임이 분명해진다. - SRP
  • 수정 시 기존의 코드를 손상하지 않고 새 커맨드들을 도입할 수 있다. - OCP
  • 유연성과 확장성을 높이고 게임 내 다양한 명령을 객체화하여 관리할 수 있다.
  • 커맨드 패턴은 각 명령마다 별도의 클래스가 필요하므로 복잡성이 증가한다.
  • 불필요한 객체화 시 코드 효율성이 떨어진다.

 

사용 예시

  • 입력 키 변경시
    • 사용자(Client)들의 입력하는 키들의 값을 바꿀 수 있게 해준다.
    • 게임 UI버튼과 상호작용 시.
  • Undo/Redo
    • 게임에서 발생된 이벤트를 되돌리거나 다시 실행 시킬 때
    • 싱글 턴제 게임에서 행동 되돌리기 등에 사용한다.

 

예시코드

 

1. 캡슐화 하기위한 인터페이스 Command 클래스.

// 구현 클래스들을 캡슐화 하기위한 추상 클래스
// Invoker와 Receiver가 직접 연결되어있지 않은 낮은 결합도 유지
class Command {
public:
	virtual ~Command() = default;
	virtual void Execute() = 0; 
};

 

2.  실제 동작을 담당하는 Receiver 구현.

// Receiver - 구현 클래스. 실제 동작
// Command를 상속받은 구현클래스. 특정 행동에 대한 실행 로직들을 캡슐화 한다.
class Skill1 : public Command {
public:
	void Execute() override {
		// Skill 1 관련 로직
	}
};

class Skill2 : public Command {
public:
	void Execute() override {
		// Skill 2 관련 로직
	}
};

 

3.  Client의 입력을 받으며, 입력받는 Key와 해당하는 스킬들을 매핑하는 Invoker

// Invoker - 사용자의 입력을 받고, Command의 실제 동작을 담당한다.
class InputHandler {
public :
	// std::unique_ptr == UE5 - TUniquePtr
	void BindKey(char Key, std::unique_ptr<Command> command) {
		keyBindings_[Key] = std::move(command);
	}

	void HandleInput(char key) {
		auto it = keyBindings_.find(key);
		if (it != keyBindings_.end() && it->second) {
			it->second->Execute();	// 해당 Key에 매핑된 행동 구현 클래스 실행
		}
	}

private:
	// 입력 Key와 행동 Skill 클래스를 매핑하기위한 UnorderedMap
	std::unordered_map<char, std::unique_ptr<Command>> keyBindings_;
};

 

4. Client는 매핑된 Key를 입력하면 그에 맞는 Receiver를 전달받으며, 수정시에도 BindKey를 사용한 할당만 하면 된다.

-> 느슨한 결합을 유지하고 있으며, 유지보수성이 높다.

	InputHandler inputHandler;

	// Client - 각 Key에맞는 Command를 바인딩한다.
	inputHandler.BindKey('Q', std::make_unique<Skill1>());
	inputHandler.BindKey('W', std::make_unique<Skill2>());

	if (IE_Pressed == 'Q')
	{
		inputHandler.HandleInput('Q');
	}
	else if (IE_Pressed == 'W')
	{
		inputHandler.HandleInput('W');
	}
	

 

 

정리

  • 디자인패턴 Behavioral Pattern중 하나.
  • 사용자의 입력을 받는 Invoker, 실제 동작 Receiver을 가지고있으며 인터페이스를 통해 캡슐화를 유지한다.
  • 수정 시 다른 코드에 영향을 주지 않는다. - OCP
  • 호출 시 Invoker는 그에 맞는 Receiver를 호출, Receiver는 실행만 담당한다. - SRP
  • 각 커맨드마다 클래스가 추가되므로 코드 내 복잡성이 증가할 수 있다.

디자인패턴은 다양한 프로그래밍 언어에서도 사용할 수 있는 기법입니다.

평소 프로그래머가 되기위해 학습을 하시는분들은 동영상이나 책 등에서의 예시를 보면 [각각의 DB에 접근하기 위해 커넥션에 대한 설정을 전략패턴을 사용하여 높은 응집도와 낮은결합성, 그리고 유지보수성을 향상시킨다.] 등의 디자인패턴이 주제가되는 등 다양한 방법으로 활용됩니다.

그렇다면, 디자인패턴의 정의 와 특징, 그리고 디자인패턴을 사용함으로써 생기는 장단점들에 대해 알아보겠습니다.

 

디자인 패턴이란?

정의

객체지향의 특징과 원칙을 기반으로 특정상황에서 문제를 해결할 수 있는 재사용 가능한 기법입니다.

 

소프트웨어 설계시에 특정상황에서 자주 만나는 문제를 해결하기위해 사용할 수 있는 재사용 가능한 솔루션으로써, 디자인패턴의 종류를 명시함으로써 설계의 의도와 해결책을 함께 설명할 수 있다.

또한, 객체지향의 4가지 특징과 5개의 원칙을 사용하여 높은 응집도, 낮은 결합성, 재사용성 및 유지보수능력이 향상된다.

 

 

특징

디자인 패턴들의 공통된 특징들은 다음과 같습니다.

  • 디자인 패턴을 사용하여 코딩시의 재사용성 및 유지보수성 증가한다.
  • 3가지(생성,구조,행위)로 나뉘어진 패턴 유형으로 존재한다.
  • 정의된 디자인 패턴을 명명하여 보다 원활한 의사소통 기능 제공한다.
  • 하나의 패턴에는 4가지의 요소*(패턴 이름, 문제, 해법, 결과)를 가지고 있다.

패턴 이름 : 디자인 패턴의 이름 한두 단어로 설계의 의도, 문제와 해법을 서술한다.

문제 : 언제 패턴을 사용하는가를 서술하며, 문제를 제시함으로써 패턴을 적용하는 것이 의미있는 사례를 정의한다.

해법 : 설계를 구성하는 요소들과 그 요소들 간의 관계 책임 그리고 협력 관계를 서술한다.

결과 : 디자인 패턴을 적용해서 얻는 결과와 장단점을 서술한다.

 

장점

  • 서로 다른 언어를 사용하더라도 디자인 패턴을 제시함으로써 특정 언어에 한정되지 않고 일반화된 솔루션을 제공할 수 있다.
  • 협업시의 개발자간 의사소통시 해결 솔루션을 특정 단어를 사용하여 원활한 의사소통이 가능하다.
  • 디자인 패턴을 명확하게 인지할 시 소프트웨어 구조 파악에 용이하다.

단점 

  • 초기 설계단계에서 기존의 코드보다 더 길어지며, 데이터의 기존 처리속도가 비교적 느릴 수 있다.
  • 설계할시 초기 난이도가 더 높다.

 

디자인 패턴의 종류와 3가지 유형

생성 (Creational Patterns) 구조 (Structural Patterns) 행동 (Behavioral Patterns)
싱글 톤(SingleTon) 어댑터(Adapter) 스트레티지(Strategy)
팩토리 메서드(Factory Methods) 브릿지(Bridge) 템플릿 메서드(Template Methods)
추상 팩토리(Abstract Factory Methods) 컴포지트(Composite) 옵저버(Observer)
빌더(Builder) 데코레이터(Decorator) 스테이트(State)
프로토타입(Prototype) 퍼사드(Facade) 비지터(Visitor)
  플라이웨이트(FlyWeight) 커맨드(Command)
  프록시(Proxy) 인터프리터(Interpreter)
    이터레이터(Iterator)
    미디에이터(Mediator)
    메멘토(Memonto)
    책임 연쇄(Chain of Responsibility)

디자인 패턴은 GoF(Gang of Four)의 디자인 패턴에서 불리우며, 4명의 개발자가 최초로 집대한 책에서 시작된 종류 및 유형이 있습니다.

 

 

 

1. 생성 패턴 (Creational Patterns)

생성 패턴은 객체의 인스턴스를 생성하는 방법과 관련된 패턴들이 있습니다.

주로 객체 생성의 복잡성을 줄이고, 인스턴스 과정을 보다 유연성있게 다루는 방법을 제공하는 유형입니다.

즉, 생성 패턴을 사용함으로써 생기는 주요 장점으로는 유연성 및 재사용성을 증가할 수 있습니다.

 

생성 패턴의 주요 특징으로는 시스템이 어떤 구체 클래스를 사용하는지에 대한 정보를 캡슐화 하며, 클래스의 인스턴스들이 어떻게 만들고 어떻게 서로 연관되어있는지의 정보은닉화를 제공합니다.

 

 

생성 패턴은 클래스 생성 패턴과 객체 생성 패턴으로 구분할 수 있습니다.

  • 클래스 생성 패턴 : 인스턴스로 만들 클래스를 다양하게 만들기 위한 용도로 상속을 사용한다.
  • 객체 생성 패턴 : 인스턴스화 작업을 다른 객체에게 넘긴다.

 

2. 구조 패턴 (Structural Patterns)

구조 패턴은 클래스나 객체를 조합하여 더 큰 구조를 형성하는 방법으로써 구조 패턴의 디자인 패턴을 사용하여 기존의 적용 전 기본 구조보다 효율성과 유연성을 개선합니다.

즉, 코드 확장성 및 유지보수 용이성, 재사용성에 중점을 두고 있습니다..

 

구조패턴의 주요 특징으로는 서로 독립적으로 개발한 클래스 라이브러리를 하나인 것처럼 바인딩을 할 수 있습니다.

또한 여러 인터페이스를 합성하여 서로 다른 인터페이스의 통일된 추상화를 제공하며, 인터페이스나 구현을 복합하는게 아닌 객체를 합성하는 방법을 제공합니다.

 

 

3. 행동 패턴 (Behavioral Patterns)

행동 패턴은 객체나 클래스 간의 협력 방법을 다룹니다. 해당 패턴을 사용함으로써 한 객체가 수행할 수 없는 작업을 여러개의 객체로 분배하여 사용하여 높은 응집도 및 낮은 결합성을 유지하는데 중점을 두고 있습니다.

 

즉, 행동 패턴을 사용하여 객체 간의 제어 구조가 아닌 객체들을 어떻게 연결할 것인지에 대한 것에 중점을 둠으로써 높은 응집도 및 낮은 결합성을 유지하는데 도움을 주는 디자인 패턴입니다.

 


정리

 

디자인 패턴은 소프트 웨어 설계시에 생기는 문제들을 해결하기위해 사용하는 재사용 가능한 솔루션이다.

디자인 패턴은 4가지의 요소를 중점으로 고안되었으며, 디자인 패턴은 3가지의 유형으로 나뉠 수 있다.

각각의 디자인 패턴을 사용함으로써 얻을 수 있는 장점으로는 코드의 유지보수 및 확장성, 유연성 증가 등이 있다.

 

예시) 템플릿 메서드 패턴을 통하여 공통적인 부분을 상위 클래스에서 높은 응집도를 나타냄으로써, 기존의 적용 전 코드보다 상대적으로 적은 코드로 인한 빌드 시간을 단축시킬 수 있다. 빌드시간이 단축되었다는건 처리시간을 보다 효율적으로 나타내었으며 즉 프로그램의 유지보수성을 향상시켰다고 볼 수 있다.

+ Recent posts