정보처리기사/프로그래밍 언어 활용
객체지향 기술 7
RangA
2023. 5. 30. 16:57
05. 디자인 패턴(Design Pattern)
01. 디자인 패턴
1) 디자인 패턴의 개념
- 유사한 문제를 해결하기 위해 설계들을 분류하고 각 문제 유형별로 가장 적합한 설계를 일반화하여 체계적으로 정리해 놓은 것으로 소프트웨어 개발에서 효율성과 재사용성을 높일 수 있음
- 생산성을 향상시키기 위해 반복적으로 나타나는 문제 해법들을 전문가들의 경험을 모아서 정리한 일관된 솔루션이라고 할 수 있음
- 디자인 패턴을 참고하여 개발할 경우 개발의 효율성과 유지보수성, 운용성 등의 품질이 높아지며, 프로그램의 최적화를 도움
- 소프트웨어 아키텍처나 소프트웨어 프레임워크와 다르기, 기능보다 구조, 가독성 및 확장성에 비중을 둠
2) GoF 디자인 패턴
- 에리히 감마(Erich Gamma), 랄프 존슨(Ralph Johnson), 존 블리시디스(John Vissides), 리차드 헬름(Richard Helm)은 소프트웨어 개발 영역에서 디자인 패턴을 구체화하고 체계화한 사람들로 GoF(Gang of Four)라고 불림
- 23가지의 디자인 패턴을 정리하고 각각의 디자인 패턴을 생성(Creational), 구조(Structural), 행위(Behavioral) 3가지로 분류함
3) 디자인 패턴의 구성 요소
구성 요소 | 내용 |
---|---|
패턴의 이름과 구분 | 패턴을 호칭하는 이름과 패턴의 유형 |
문제 및 배경 | 패턴이 적용되는 분야 또는 배경, 해결하는 문제를 의미 |
솔루션 | 패턴을 구성하는 요소, 관계, 협동 과정 |
사례 | 간단한 적용 사례 |
결과 | 패턴을 사용할 때 이점이나 영향 |
샘플 코드 | 패턴이 적용된 원시 프로그램(소스 코드) |
4) 디자인 패턴의 장단점
- 디자인 패턴의 장점
- 개발자들 간의 원활한 의사소통이 가능함
- 소프트웨어의 아키텍처를 파악하기 용이함
- 재사용성과 확장성이 좋아 개발 시간을 단축시킬 수 있음
- 설계 변경에 따른 유연성, 이식성이 좋음
- 디자인 패턴의 단점
- 객체지향 개발 위주로만 사용할 수 있음
- 초기 비용이 많이 듦
5) 디자인 패턴의 분류
- 생성(Creational) 패턴
- 객체를 생성하는 데 사용되는 패턴
- 클래스 정의와 객체 생성 방식을 구조화, 캡슐화한 방법을 제시함
- 시스템이 어떤 구체적인 클래스를 사용하는지에 대한 정보를 캡슐화함
- 객체를 생성하거나 수정되어도 프로그램 구조에 영향을 적게 받도록 함
- 캡슐화하여 부작용을 최소화함
- 종류 : 추상 팩토리(Abstract Factory), 팩토리 메소드(Factory Method), 빌더(Builder), 프로토타입(Prototype), 싱글톤(Singleton)
- 구조(Structural) 패턴
- 여러 개의 객체를 모아 구조화 시키는 패턴
- 여러 개의 객체에 접근할 수 있는 인터페이스를 제공함
- 여러 개의 객체를 모아 새로운 기능을 제공하게 함
- 다른 기능을 가진 객체가 협력에 의해 어떠한 역할을 수행할 때 객체를 조직화 시키는 일반적인 방식을 제시함
- 종류 : Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy
- 행위(Behavioral) 패턴
- 객체의 구체적인 알고리즘을 정의하는 패턴
- 큰 작업을 여러 개의 객체로 분리한 방법을 제공함
- 반복적으로 사용하는 객체들의 상호 작용을 패턴화한 것으로 객체의 행위를 조직화, 관리, 연합하는데 사용되는 패턴
- 객체 사이의 결합도를 최소화함
- 알고리즘 수행에 주로 이용됨
- 종류 : Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor
02. 디자인 패턴 종류 - 생성 패턴
1. Abstract Factory 생성 패턴
- 여러 개의 연관된 서브 클래스를 특정 그룹으로 묶어 한 번에 수정할 수 있도록 만든 패턴
- 생성 군들을 하나에 모아 놓고 팩토리 중에서 선택하게 하는 패턴
- 같은 종류의 객체들을 일관된 방식으로 생성하는 경우에 유용함
- 관련이 있는 서브 클래스를 묶어서 팩토리 클래스로 만들고, 이들 조건에 따라 객체를 생성하는 패턴
- 여러 개의 클래스를 하나의 추상 클래스로 묶어 한 번에 교체할 수 있는 패턴
- 제품, 운영체제, 회사별로 유사한 제품이지만 지원하는 기능에 차이가 있을 경우 기능별로 통합하여 운영할 때 유리함
- 추상 팩토리 패턴은 팩토리 메소드 패턴을 확장한 캡슐화 방식
2. Factory Method 생성 패턴
- 객체를 만들어내는 공장을 만드는 패턴
- 서브 클래스가 인스턴스를 결정하도록 하고 책임을 위임하는 패턴
- 객체의 생성을 서브 클래스에 위임하는 패턴
- 객체를 생성하기 위한 인터페이스를 정의하여 어떤 클래스가 인스턴스화 될 것인지 서브 클래스가 결정하도록 하는 것
- 조건에 맞게 객체를 다르게 생성해야 할 때 사용하는 패턴
- 사용자의 입력 값이나 조건이 다를 경우 조건에 맞는 다른 객체를 생성할 때 필요한 패턴
- 메인 클래스에서 객체 생성을 줄일 수 있음(new 사용을 줄임)
- 객체 간의 결합도를 줄이고 유지보수가 용이하게 됨
- 템플릿 메소드 패턴을 사용함
- Virtual-Constructor 패턴이라고도 함
3) Builder 생성 패턴
- 객체의 생성에 있어서 복잡한 과정들을 분리함
- 생산 단계를 캡슐화하여 구축 공정을 동일하게 이용하도록 하는 패턴
- Builder 패턴은 복잡한 객체를 단계적으로 생성하는 것에 초점을 둠
- 많은 인수를 가진 객체를 생성할 때 다른 객체의 도움으로 생성하는 패턴
- 데이터의 순서에 상관없이 객체를 만들어 냄
- Builder 패턴은 생성자 초기화 문제 때문에 만들어짐
4) Prototype 생성 패턴
- 성능 향상을 위해 중복 객체를 생성하는 패턴
- new를 사용하지 않고, 복사해서 객체를 생성함
- 객체를 생성할 때 드는 비용을 줄이기 위해 사용함
- Prototype을 생성해 놓고, 나중에 복제해서 객체를 생성함
- 생성하는 객체가 동일하고 객체의 값이나 크기가 변하게 될 때 유용함
5) Singleton 생성 패턴
- 한 클래스에 한 객체만 존재하도록 제한하는 패턴
- 오직 하나의 인스턴스만을 가지도록 하는 패턴
- 낭비되는 동일한 인스턴스가 여러 개 존재하여 성능 저하가 되지 않도록 하는 패턴
- new를 한 번만 실행할 수 있도록 제한해야 함
- 유일한 멤버 변수가 되기 위해서는 Static으로 선언함
- Private으로 접근을 제한해야 함
03. 디자인 패턴 종류 - 구조 패턴
1) Adapter 구조 패턴
- 국내 가전제품을 외국에서 사용한다고 할 때, 동일한 전압을 사용하지 않는다면 중간에 변환 코드가 필요한데, 이런 변환 코드를 Adapter 구조 패턴이라고 함
- 인터페이스로 인해 함께 사용하지 못하는 클래스를 함께 사용하도록 하는 패턴
- 호환성이 없는 인터페이스 때문에 함께 동작할 수 없는 클래스들을 함께 동작하도록 해줌
2) Bridge 구조 패턴
- 하나의 클래스 계층에 복잡하게 존재하는 기능 클래스와 구현 클래스를 분리하여, 두 개의 클래스를 연결하여 사용하는 패턴
- 추상과 구현을 분리하여 결합도를 낮춘 패턴
- Bridge 구조 패턴은 기능 클래스와 구현 클래스를 연결해줌
- 기능과 구현을 구분하여 필요한 부분을 독립적으로 추가할 수 있음
- Extends는 견고한 연결이고, Bridge는 느슨한 연결
- 상속은 클래스를 확장하기 위해 편리한 방법이지만 클래스 간의 연결을 강하게 고정함
- 기능을 추가하고 싶으면 기능 클래스 계층에 클래스를 추가함
- 프로그램의 필요에 따라서 클래스 간의 관계를 손쉽게 바꾸고 싶을 때는 브릿지 패턴을 사용함
3) Composite 구조 패턴
- 개별 객체와 복합 객체를 클라이언트에서 동일하게 사용하도록 하는 패턴
- 여러 개의 클래스를 모아서 마치 하나의 클래스처럼 취급하게 함
- 복합 객체와 단일 객체를 동일하게 취급하거나 다룰 수 있음
- 복합 객체와 단일 객체의 처리 방법이 다르지 않으면 전체와 부분 관계로 정의할 수 있음
- 트리 구조 형태를 다룰 때 유용함
- 대표적인 예는 Directory-File 구조 형태
4) Decorator 구조 패턴
- 소스를 변경하지 않고 기능을 확장하도록 하는 패턴
- 기존 객체의 메소드에 새로운 행동을 추가하거나 오버라이딩 할 수 있음
- 객체에 독립적인 기능을 계속해서 추가, 확장할 때 유용함
- 객체에 부가적인 기능을 동적으로 추가할 때 사용하는 패턴
5) Facade 구조 패턴
- 복잡한 시스템을 구조화하여 쉽게 사용할 수 있또록 하는 패턴
- 하나의 인터페이스를 통해 느슨한 결합을 제공하는 패턴
- 클라이언트와 복잡한 서브 시스템 사이에 Facade가 존재하게 함
- Facade 패턴을 사용하면 서브 시스템의 복잡한 구조를 의식하지 않아도 됨
- 많은 서브 시스템들이 바람직하지 않은 결합도를 갖거나 서브 시스템들의 구현이 바뀌어 혼잡할 때 사용하면 유용함
- 서브 시스템들을 감싸는 하나의 접속 지점을 정의한 후 통합된 인터페이스를 제시하고 서브 시스템들과 협력할 책임을 가짐
- Facade 패턴에서 제공하는 단순화된 하나의 인터페이스만 사용하므로 클래스 간의 의존 관계가 줄어들고 복잡성 또한 낮아지는 효과를 가져옴
- 고수준의 인터페이스를 사용하므로 서브 시스템을 쉽게 사용할 수 있음
- 메소드를 단순화하여 라이브러리를 쉽게 사용하고 이해할 수 있게 함
6) Flyweight 구조 패턴
- 대량의 작은 객체들을 공유하는 패턴
- 유사한 객체를 공유해서 비용을 절감할 수 있음
- 메모리를 가볍게 유지시키는 데 유용함
- 자주 사용하는 데이터나 코드를 중복 생성하지 않도록 관리하는 풀(저장소)을 만들어 필요할 때마다 불러 사용할 수 있도록 함
7) Proxy 구조 패턴
- 객체의 대리자를 이용하여 다른 객체로의 접근을 통제하는 패턴
- 대리 객체를 통해 원래 객체의 작업을 대신 수행하도록 함
- 복잡한 작업과 단순한 작업을 나누어서 처리할 수 있는 패턴
- 원래의 기능을 수행하면서 부가적인 기능을 수행할 때 유용함
- Proxy 구조 패턴의 종류
- Remote Proxy : 원격으로 접속하는 기능을 대리 사용함
- Virtual Proxy : 가상적인 자원을 사용하고 할 때 사용함
- Protection Proxy : 보안이 요구되는 객체에 접근을 통제할 때 사용함
- Smart Reference Proxy : 부가적인 작업을 수행할 필요가 있을 때 사용함
04. 디자인 패턴 종류 - 행위 패턴
1) Chain of Responsibility 행위 패턴
- 하나의 문제가 발생했을 경우 그 문제의 처리를 담당하는 여러 개의 처리기를 두고 순서대로 처리해 나가는 패턴
- 객체를 연결 리스트와 같이 연결한 후 현재 요구를 수행하지 못하는 객체라면 다음 객체에 책임을 넘기는 형태의 패턴
- Chain of Responsibility를 사용하면 후보 객체들을 모두 알 필요 없이 자신과 연결된 후보 객체만 알면 됨
- 어떤 요구에 대해 처리해주는 객체의 위치를 파악하기 힘든 경우에 유용함
- Strategy 패턴은 하나의 노드에서 특정 알고리즘을 선별하여 사용하지만, Chain of Responsibility 패턴은 하나의 메시지가 다양한 노드에 존재하는 알고리즘의 적용을 거치게 함
- Visitor 패턴은 자신의 알고리즘이 노드에서 노드로 옮겨지면서 적용되지만 Chain of Responsibility 패턴은 하나의 메시지가 다양한 노드에 존재하는 알고리즘의 적용을 거치게 됨
2) Command 행위 패턴
- 여러 기능을 실행할 수 있도록 재사용성이 높은 클래스를 설계하는 패턴
- 서비스를 호출할 때 융통성을 높이려고 사용하는 패턴
- 매개 변수를 사용하여 여러 가지 다른 요구사항을 처리할 수 있음
3) Interpreter 행위 패턴
- 간단한 언어의 문법을 정의하고 해석하는데 사용되는 패턴
- SQL 구문 분석, 기호 처리 등에서 사용되는 패턴
- Text 문장을 해석하도록 지시하는 표현 인터페이스를 구현함
4) Iterator 행위 패턴
- 반복이 필요한 자료 구조를 모두 동일한 인터페이스를 통해 접근할 수 있도록 하는 패턴
- 표현 방법을 자세하게 나타내지 않고 객체의 자료들을 순차적으로 접근하는 데 사용하기 유용함
- 검색 기능을 자료 구조와 분리 시켜 객체로 만들면 됨
5) Mediator 행위 패턴
- 여러 객체 간의 통신 복잡성을 줄이기 위해 사용되는 패턴
- 복잡한 상호 작용 관계를 단순화시킬 수 있음
- 서로 다른 클래스 간의 모든 통신을 처리하고, 약한 결합으로 코드를 쉽게 유지 관리할 수 있는 중재자 클래스를 제공함
6) Memento 행위 패턴
- 객체의 상태를 저장해두었다가 복원해야 할 경우 사용하는 패턴
- 캡슐화의 원칙을 지키면서 객체의 내부 상태를 파악하고 객체의 상태를 저장해둔 상태로 다시 복구할 수 있게 함
7) Observer 행위 패턴
- 의존적이고 종속된 다른 객체들의 변화를 통지 받고 자동으로 갱신해주는 패턴
- 어떤 클래스에 변화가 있을 때, 이를 감지하여 다른 클래스에 통보해줌
- 상태가 변경되었을 경우 다른 객체에 의존하지 않으면서 데이터 변경을 통보하고자 할 때 유용함
8) State 행위 패턴
- 규칙에 따라 객체의 상태를 변화 시키면서 객체가 할 수 있는 행위를 바꾸는 패턴
- 특정 메소드가 객체의 상태에 따라 다른 기능을 수행함
- 객체의 상태에 따라 동일한 루틴에서 다른 행동을 할 수 있음
9) Strategy 행위 패턴
- 클래스별로 캡슐화되어 있는 객체들을 교체할 수 있도록 함으로써 같은 작업을 다른 알고리즘으로 사용할 수 있도록 하는 패턴
- 다형성을 이용하여 특정 객체에 종속되지 않도록 하며, 다른 부분을 분리하여 캡슐화함
- 상황에 맞게 행위를 변경하고 싶을 때 유용함
10) Template Method 행위 패턴
- 작업의 일부분을 캡슐화하여 전체 일을 수행하는 구조는 그대로 유지하면서 특정 부분을 바꾸는 패턴
- 알고리즘을 메소드로 정의하고 하위 클래스에서 알고리즘 구조의 변경 없이 알고리즘을 재정의하는 패턴
- 공통적인 작업 흐름은 추상 클래스에서 정의하고 나머지 구현들은 각각의 서브 클래스에서 담당하게 함
- 전체적으로 동일하면서 부분적으로는 다른 메소드의 코드 중복을 최소화할 때 유용함
11) Visitor 행위 패턴
- 기존 객체의 구조를 수정하지 않고 새로운 기능을 추가할 수 있는 패턴
- 멤버 변수롸 멤버 메소드를 다른 클래스로 분리하여 서로 간에 호출하게 함
- 메소드 추가를 자유롭게 함
- 클래스의 구조를 변경하지 않으면서 새로운 기능을 추가할 때 유용함