2024. 7. 15. 22:18ㆍ카테고리 없음
# 디자인 패턴
- 개념: 과거의 소프트웨어 개발 과정에서 발견된 설계의 노하우를 정리하여 이름을 붙인 것 / 자주 발생하는 문제에 대한 검증된 해결책
# 생성 패턴(추상 객체 인스턴스화)
1. 추상 팩토리(Abstract Factory)
- 많은 수의 연관된 서브 클래스를 특정 그룹으로 묶어 한 번에 교체할 수 있도록 만드는 패턴
- EX) 특정 그룹 1에서는 마린/파이어뱃/메딕(서브 클래스)만 나오고, 특정 그룹 2에서는 벌쳐, 골리앗, 탱크가 나옴
2.팩토리 메서드(Factory Method)
- 객체를 만들어 반환하는 함수를 생성자 대신 제공하여 초기화 과정을 외부에서 보지 못하게 숨기고 반환 타입을 제어하는 방법
# Singleton Pattern
- 프로그램 내에서 인스턴스가 하나만 존재해야 하고 어디에서든 인스턴스에 접근할 수 있도록 하는 패턴
- 클래스 내에서 인스턴스가 단 하나뿐임을 보장하므로, 프로그램 전역에서 해당 클래스의 인스턴스를 바로 얻을 수 있고 메모리 낭비를 최소화함
- 생성자를 다른 클래스에서도 사용할 수 있으면 그곳에서도 인스턴스를 만들 수 있게 되기 때문에 생성자를 클래스 자체에서만 사용할 수 있도록 접근제한자 private 등을 통해 제한하여야 함
<초기화 방법>
1. 사전 초기화
- 클래스 로딩 시에 인스턴스를 생성하는 방법
- 멀티스레드 환경에서의 이중 객체 생성 문제가 없음
- 인스턴스를 호출하지 않아도 무조건 클래스를 초기화하기에 메모리 효율이나 연산 효율은 낮음
2. 사후 초기화
- 인스턴스를 실제로 사용할 시점에 인스턴스를 생성하는 방법
- 이중 객체 생성 문제가 발생할 수 있으나, 인스턴스를 실제로 사용하지 않으면 메모리와 연산량을 아낄 수 있음
- 사용처: 로그 기록 객체, 유저매니저, 데이터 테이블 정보를 저장하는 클래스
<예시>
data class User (
var Id: String, var nickname: String,
var startupField: String, var password: String) {
}
// 전 클래스에 공유되는 instance를 object에서 User를 일괄적으로 관리
object UserManager {
val users = mutableListOf<User>()
fun createUser(Id: String, nickname: String, startupField: String, password: String) {
users.add(User(Id, nickname, startupField, password))
}
fun findUser(Id_: String): User? {
return users.find { it.Id == Id_ }
}
fun deleteUser(Id__: String) {
users.remove(users.find { it.Id == Id__ })
}
}
# Strategy Pattern
- 알고리즘을 캡슐화해 교체하여 사용할 수 있도록 한 구조
- 알고리즘 인터페이스를 정의하고 인터페이스를 상속받은 클래스에 알고리즘을 구현하여 캡슐화
- 알고리즘을 사용할 클래스에 인터페이스를 포함
- 상속으로 해결할 수 없는 코드 중복이나 객체의 실시간 알고리즘 변경 시 유용'
- 신규 알고리즘 추가 및 수정이 용이
- OPP 디자인적 관점에 맞지 않음
- 사용처: 게임 룰을 모드별로 다르게 적용하고 싶을 때 / 상황에 따라 길찾기 알고리즘을 바꾸고 싶을 때
<예시>
텍스트를 좌/우/중앙 정렬하는 함수를 Strategy Pattern을 활용해서 만들어야 함.
(조건)
1. `TextAlignmentStrategy` 인터페이스를 정의합니다.
2. 세 가지 정렬 전략(왼쪽, 오른쪽, 중앙)을 구현합니다.
3. `TextEditor` 클래스는 `TextAlignmentStrategy`를 사용하여 텍스트를 정렬합니다.
package com.example.strategypatternpractice
// Strategy 인터페이스 정의: 알고리즘을 캡슐화하는 작업을 수행하는 인터페이스를 생성
// TextAlignmentStrategy 안에 텍스트를 좌/우/중 정렬하는 각 함수가 상속받은 alignText 함수를 정의
interface TextAlignmentStrategy {
fun alignText(text: String) {
}
}
package com.example.strategypatternpractice
// ConcreteStrategy 클래스들: Strategy 인터페이스를 구체적으로 구현하는 알고리즘 클래스를 정의
// 인터페이스를 상속받는 좌정렬함수 alignLeft() 를 정의 -> 갈아끼울 첫번째 클래스
class alignLeft: TextAlignmentStrategy {
// 인터페이스의 alignText()를 상속받아서, 텍스트를 좌로 정렬하는 기능을 추가
// 디폴트가 좌정렬이라 따로 추가하진 않고 바로 println(text)
override fun alignText(text: String) {
println(text)
}
}
// 인터페이스를 상속받는 우정렬함수 alignLeft() 를 정의 -> 갈아끼울 두번째 클래스
class alignRight: TextAlignmentStrategy {
// 인터페이스의 alignText()를 상속받아서, 텍스트를 우로 정렬하는 기능을 추가
override fun alignText(text: String) {
println(text.padStart(30))
}
}
// 인터페이스를 상속받는 중앙정렬함수 alignLeft() 를 정의 -> 갈아끼울 세번째 클래스
class alignMiddle: TextAlignmentStrategy {
// 인터페이스의 alignText()를 상속받아서, 텍스트를 중앙으로 정렬하는 기능을 추가
override fun alignText(text: String) {
val padding = (30 - text.length) / 2
println(text.padStart(padding + text.length).padEnd(30))
}
}
package com.example.strategypatternpractice
// Context클래스: Strategy 클래스를 사용하는 클래스
// Strategy 객체를 본격적으로 사용하는 클래스를 생성
class TextEditor(private var alignment: TextAlignmentStrategy) {
// 갈아끼울 캡슐을 좌정렬/우정렬/중앙정렬 클래스 중 선택하는 setAlignment() 함수를 정의
fun setAlignment(alignment: TextAlignmentStrategy) {
// 좌정렬/우정렬/중앙정렬 클래스 중 쓸 클래스를 선택.(캡슐을 갈아끼우기)
this.alignment = alignment
}
// 텍스트를 정렬하는 함수를 정의
fun alignText(text: String){
// this.alignment = alignment에서 갈아끼운 클래스에서 실질적으로 동작하는 함수를 실행
return alignment.alignText(text)
}
}
fun main(){
// 캡슐 갈아끼우고 실행 - 좌정렬
val textEditor = TextEditor(alignLeft())
textEditor.alignText("Hello World!")
// 캡슐 갈아끼우고 실행 - 우정렬
textEditor.setAlignment(alignRight())
textEditor.alignText("Hello World!")
// 캡슐 갈아끼우고 실행 - 중앙정렬
textEditor.setAlignment(alignMiddle())
textEditor.alignText("Hello World!")
}
# Observer Pattern
- 하나의 객체가 여러 객체에 영향을 미칠 때, 객체들 간에 일일이 연결을 만드는 대신 여러 객체들이 하나의 객체를 관찰한는 패턴을 만들어 중점이 되는 개체가 변화할 때 그 변화를 연결된 여러 옵저버들에게 전달하는 패턴
- 한 개의 클래스가 여러 개의 클래스와 연결되어 있을 때 이 클래스들 간의 연결을 최소화하고 주체가 옵저버에게 정말 필요한 정보(알림)만을 여러 클래스에 보내주는 패
- 객체의 상태 변화를 관찰하는 관찰자들을 객체가 갖고 있다가 상태 변화가 있을 때 통지하는 패턴
- 일대다 의존성 정의
- 사용처: GUI, 채팅 프로그램
# Decorator Pattern
- 객체에 추가적인 요소들을 동적으로 추가하는 패턴
- 기본 클래스의 서브 클래스를 구성하여 생성 시 상속받은 클래스를 넘겨서 확장할 수 있도록 함