#1 개요
https://www.youtube.com/watch?v=Pzy_MPfGixg&t=15s
니코쌤의 유튜브를 보다가 재밌어 보여서 여러가지 디자인 패턴을 찾아보고 싶었다.
디자인 패턴은 소프트웨어 개발 중 생기는 문제점에 대한 일반적인 문제를 해결하는 방법론이다. 문제를 해결하기 위해서 사람들이 사용했던, 표준화 된 모범사례의 종류라고 할 수 있다.
프로젝트를 파익할 때, 어떤 디자인 패턴을 사용하는 프로젝트인지 알아볼 수 있다면 조금 더 쉽게 프로젝트를 파악할 수 있다.
디자인 패턴의 하위 카테고리는 세가지로 나뉜다.
생성(creational) : 여러가지 상황에 맞는 객체 생성 방법론을 모아둔 카테고리. 객체 생성 방식에 독립적인 시스템을 만드는 방법이다. 결과적으로 객체로 인해 코드가 유연하고 재생산 가능하도록 하는게 목표이다.
[찾아본 생성 예시들 : builder 패턴, abstract factory 패턴, factory method 패턴]
구조(structural) : 큰 시스템을 만들 때, 여러 '클래스'를 구성하고 결합하는 방법론으로, 시스템이 유연성과 확장성을 가지도록 만드는 방법론을 모아둔 카테고리이다. 시스템의 각 부분을 서로 독립적으로 만들어 결합도를 낮추는게 목표중 하나이다.
[찾아본 구조 예시들 : Facade 패턴, Birdge 패턴, Decorator 패턴, Adapter 패턴, Proxy패턴]
행위(behavioral) : 객체간 혹은 객체와 클래스간 서로 통신하는 방법론을 모아둔 카테고리.
[찾아본 행위 예시들 : Observer 패턴, visitor 패턴]
참고한 블로그
https://refactoring.guru/ko/design-patterns
#2 생성 패턴의 예시들
1) Builder 패턴
(a) 문제: 하나의 Class에 생성자가 많이 필요한 경우
(b) 디자인 패턴을 사용하지 않을 경우:
class house(){
constructor(){
public rooms:Number;
public doors:Nubmer;
public windows:Nubmer;
//... 등등 문제를 크게 보아 10개 20개씩 있다고 가정해보자
}
}
이러면 객체를 생성할 때 어떻게 될까?
//되게 길어지며 어떤 생성자의 값인지 알아내기도 어려워짐.
new house(1, 2, 2, ...);
(c) builder 디자인 패턴을 사용한 경우
house라는 class에서 constructor에 값을 넣어 객체를 생성하는 것이 아닌,
house의 constructor의 역할을 할 builder class를 하나 만들어주는 것.
이 builder class의 각 메소드들은 house 하나의 속성(값)당 하나를 담당하게 됨.
class house(){
public rooms = 0;
public doors = 0;
public windows = 0;
//...
}
위와 같이 class를 하나 만들어두고,
class HouseBuilder{
//먼저 class 선언
private house : House;
constructor(){
//생성자로 객체 생성
this.house = new House();
}
public setRooms(roomNum: Number) : HouseBuilder{
this.house.rooms = roomNum;
return this;
}
public setWindows(windowNum: Number) : HouseBuilder{
this.house.windows = windowNum;
return this;
}
public build() : House{
return this.house;
}
}
method는 특이하게 빌더 그 자체인 this를 반환한다.
그리고 이렇게 위 method들로 모든 속성에 값을 넣어주는게 끝나면 builder() 메소드로 객체 내 house를 반환하는 메소드가 있다.
이렇게 작성된 코드에서 house를 만드는 방법은 곧 house builder에 인스턴스를 할당하는 방법이 된다.
const houseOne = newHouseBuilder().setRoomse(4).setWindows(2).build();
const housetwe = newHouseBuilder().setRoomse(2).setWindows(1).build();
이러한 방식은 가독성을 올려줄 뿐만 아니라, 새로운 속성을 추가할 때 builder에 새로운 method를 만들어주기만 하면 되는 등 확장성도 보장해준다.
2) 추상 팩토리 패턴
https://refactoring.guru/ko/design-patterns/abstract-factory
추상 팩토리 패턴
/ 디자인 패턴들 / 생성 패턴 추상 팩토리 패턴 다음 이름으로도 불립니다: Abstract Factory 의도 추상 팩토리는 관련 객체들의 구상 클래스들을 지정하지 않고도 관련 객체들의 모음을 생성할 수 있
refactoring.guru
3) Factory Method 패턴
객체를 생성하기 위한 인터페이스를 정의하여, 어떤 클래스가 인스턴스화 될 것인지를 서브 클래스가 결정하도록 하는 방식.
#3 구조 패턴의 예시들
1) Facade 패턴
건물 외관을 뜻하는 Facade에서 따온 명칭으로 복잡한 시스템을 감추고 가독성을 올려주는 방식.
하나의 동작을 위해 작은 동작들이 필요할 때 사용한다.
미리 요약하면 Class내부에 하나의 기능을 위한 메소드를 만들고, 그 내부에 다양한 함수를 넣어서 해당 기능을 메소드 하나로 사용하는 것처럼 보이게끔 하는것.
(a) 문제: 하나의 상황에 여러가지 기능을 수행해야 한다면?
(b) 생략
(c) 스마트홈 시스템을 예시로 기능을 사용하는 경우
불, 전등, 보안 등 여러가지 다른 Class와 해당 Class내부에는 다양한 method들이 있다.
집을 나설 때, 수행하게 될 각각의 Class마다의 method를 하나로 묶어서 '외출'기능에 만드는 것이다.
class SmartHome {
private lights: Lights;
private aircon: Aircon;
private security: Security;
constructor(){
this.lights = new Lights();
this.aircon = new Aircon();
this.security = new Security();
}
//외출할 때 수행할 method
public leaveHome():void{
this.lights.turnOff();
this.aircon.turnOff();
this.security.on();
}
}
2) Bridge 패턴
(1) 정의: 브리지는 관련된 클래스 집합을 계층구조로 만들어서 독립적으로 개발할 수 있게 하는 법.
즉, class 조합 가지수가 너무 많아지지 않도록 하는 방법론이다.
(2) 문제
(3) 해결
3) Decorator 패턴
(1) 정의
(2) 문제
(3) 해결책
상속 관계와 집합관계를 이용하여 Decorator를 만든다.
4) Adapter 패턴
(1) 정의
Adapter는 호환되지 않는 인터페이스를 가진 객체들끼리 협업할 수 있도록 'Class 단에서 디자인 패턴을 적용하는 구조적 패턴'이다.
(2) 문제
(3) 사용되는 방식
5) Proxy 패턴
(1) 정의
Proxy는 원래 사용하려는 객체 대신, 다른 객체를 사용해서 그 자리를 대체하도록 할 수 있는 구조적 디자인 패턴이다.
이런 방식이 왜 필요할까? 캐싱을 떠올리면 된다.
(2) 문제 상황
(3) 사용 결과
#4 행위 패턴의 예시들
1) Observer 패턴
(a) 문제 상황: 애플리케이션의 한 부분이 변경되면 나머지 부분도 변경되도록 시스템을 짜야할 때.
(b) 디자인 패턴을 사용하지 않는 경우: if문 같은 형태로 변화를 판단하여 일일히 class에 접근해서 해결해야함.
(c) 디자인 패턴 사용법
객체와 Observer라는 두가지 요소를 만들어 사용하게 된다.
Observer는 객체를 관찰하는 Class이다.
먼저 Observer라는 추상 Class를 만들고, 해당 Class를 상속하는 객체가 Observer 요소가 되도록 설계한다.
이제 내부에 Observer들을 선언하는 몸통인 객체를 만들어 준다.
이후 각 Observer에게 반복문을 사용해서 상태를 전달하는 method를 하나 만들고,
또 이 method에게 상태를 전달하는 method들을 만들어서 사용한다.
class Band {
private observers: Observer[] = [];
//위의 observer 배열에 observer를 추가해주는 메소드
//위의 observer 배열에 observer를 제거해주는 메소드
//observer에 변경을 알리는 메소드
//이 코드로 observer들은 상태 변화를 받게되고 해당 상태에 따른 역할을 수행하게 된다.
notifyObservers(event : string): void{
this.observers.forEach(observer => {
observer.notify(event);
})
}
//위 notifyObserver에 직접 string을 입력해주기보다는 method로 넣어주는게 보기 좋다.
startConcert() :void{
this.notifyObservers("START");
}
}
2) Visitor 패턴
(1) 정의
Visitor(방문자) 패턴은 객체를 통해 작동하는 기능들을 객체들로부터 분리할 수 있도록 하는 행동 디자인 패턴임.
따라서 어떤 기능을 수행할 때, 마치 방문자처럼 객체들에게 인식되어서 사용됨.
(2) 문제
특정 기능을 다양한 Class에 추가해줘야 한다고 가정하자.
(3) 디자인 패턴을 사용한 해결법
기존 Class 내부에 이 기능을 추가하는 것이 아닌, visitor로서 보내는 방식을 취하는게 이 디자인 패턴이다.
#5 모든 디자인 패턴 종류 한 눈에 보기
'주저리' 카테고리의 다른 글
[210619] Alpha Go - The movie 를 보고 (0) | 2021.06.19 |
---|