22/12/10

송은우·2022년 12월 10일
0

TIL

목록 보기
46/61

CI/CD
플랫폼 명시

머지 커밋 생성시 버전 명세
blue-green 배포시 무거운 api 가 작동중에 종료될 수 있음
nginx 프론트, 백엔드를 나누는 것이 좋아보임
동시 배포시 두 nginx 가 파일을 건드릴 수 있기에 충돌 가능

refectoring.guru

싱글톤 패턴은
2가지 일을 하기에 단일 책임을 깬다
전역 접근 지침을 제공하고, 객체가 하나만 있도록 하는 일을 한다

싱글톤

static instance
static getInstance(){
if(instance!=null){
	return instance;
}
synchronized(Singleton.class){
	if(instance==null){
    	instance=new instance();
    }
}

로 생성해야 멀티 쓰레드 환경까지 모두 보장 가능

전역 변수를 더 엄격하게 제어해야 할 때 사용
정적 팩토리 내에서 지연 초기화를 해야됨
컴포넌트들이 서로를 너무 많이 알고 있는 경우를 만들 수 있음
멀티 쓰레드도 생각해야됨
유닛테스트도 어려움

공유된 상태를 단 하나의 플라이웨이트 객체로 줄일 수 있다면 플라이웨이트와 유사할 수 있음
싱글턴은 하나의 인스턴스, 플라이웨이트는 고유한 상태의 여러 인스턴스. 싱글턴 객체는 변할 수 있고, 플라이웨이트는 변할 수 없음

factory 패턴
서로 다른 하위 타입을 공통된 인터페이스로 추상화 시킨 후, 제공되는 생성자르 ㄹ제공할 경우 쓰는 곳에서는 내부 구현을 모르고 인터페이스만으로 접근 가능함

사용 조건은
1. 객체가 정확하게 어떤 유형인지 몰라도 되는 경우, 의존관계를 모르는 경우
2. 이미 사용되는 로직은 정해져있고, 그 안에 세부 구현만 바뀌어야 되는 경우

목적
1. 생성 코드와 사용 코드를 분리함
도메인에서 객체를 생성하는 책임이 중요한 경우 분리하면 도움이 됨
2. 프레임워크나 라이브러리 내부 구현을 확장하게 시킬 수 있따
3. 객체를 재사용 하고 싶을 경우 사용한다

조건
1. 모두 같은 인터페이스를 따라야 함
2. 크리에이터 클래스 안에 빈 생성자 추가. 반환 타입은 인터페이스와 일치해야됨
3. 생성자에 대한 참조를 없애야 됨
4. 자식들의 집합 생성 후 생성자 오버라이딩
5. 자식들의 경우 공통을 또 모아서 한 단계를 더 거칠 수도 있음
6. 생성자에 매개변수를 받는 것도 당연히 가능함

iterator과 잘 쓰임
프로토타입은 복제한 객체의 초기화 작업이 복잡함. 팩토리는 초기화 작업이 없음
템플릿 메서드의 특수화, 대규모 템플릿 메서드의 한 단계도 팩토리가 가능함

추상팩토리
공통된 객체 군을 생성하기 위해서 사용됨
팩토리 메서드를 여러개 모아놓은 인터페이스를 둔다
클라이언트로부터 팩토리 인터페이스만을 노출한다
config를 통해 보통 찾게 됨
클래스가 여러 제품 유형을 상대할 경우 팩토리 메서드들은 독립 실행형 팩토리 클래스, 또는 추상 팩토리로 추출할 가치가 있을 수 있음

구현 방식
1. 제품 유형, 변형 제품들을 나타내는 매트릭스를 매핑
2. 변형 제품에 대한 추상 인터페이스
3. 각 제품 변형에 대해 각각 하나의 구상 팩토리 클래스 집합 만들기
4. 팩토리 초기화 코드를 앱 어딘가에 만들고 저장한 후 전달한다
5. 직접 호출 대신 간접 호출로 변경한다

팩토리로 시작해 추상팩토리, 프로토타입, 빌더로 발전
빌더는 단계적 생성이 중점
추상 팩토리는 객체 패밀리를 생성하는 것에 중점
빌더는 제품 가져오기 전 몇 단계의 추가 생성 단계 가능
추상 팩토리는 팩토리 메서더들의 집합을 기반으로 할 수도, 프로토타입을 이용할 수도 있음
추상 팩토리는 퍼사드 패턴 대신 사용 가능
추상팩토리 + 브릿지 조합도 가능
추상팩토리, 빌더, 프로토타입은 모두 싱글턴으로 가능

빌더
복잡한 객체들을 단계별로 생성할 수 있또록 하는 생성 디자인 패턴
제작 코드를 사용해 다양한 유형들과 표현을 제작할 수 있음

아주 많은 매개변수가 필요한 생성자 같은 경우 모든 생성자가 꼭 필요하지는 않을 수 있음
이때 null이 들어가는 모습이 안 좋음

디랙터 클래스
빌더 단계들에 대한 일련의 호출을 담당함
매퍼라고 봐도 무방할 듯?
없어도 되긴 함

빌더 패턴이 일부 제품의 다른 표현들을 생성할 수 있고 하고 싶으 때 사용할 수 있음
세부사항만 다른 유사한 단계를 포함할 경우 쓸 수 있음
빌더는 복합체 트리들 또는 복잡한 객체를 생성할 수 있음
생성 단계의 미완성 제품을 노출하지 않음. 불완전한 결과가 생기지 않음(생성시 optional이 많은 경우 특히 유리한듯)

공통 생성 단계가 명확해야 한다
디렉터 클래스를 만드는 것도 좋음. 같은 빌더 객체로 다양한 제품이 캡슐화 될 수 있음
클라이언트가 디렉터에게 빌더 객체를 전달함
모든 제품이 같은 인터페이스만 사용 하는 경우 직접 생성 결과를 얻을 수 있음

빌더 + 브릿지가 가능

프로토타입

그들의 클래스에 의존하지 않고, 기존 객체를 복사하는 방법
보통 단일 clone을 통해서 생성하지만 이 clone은 모든 클래스마다 비슷하다는 것이 있음
복제를 지원하는 객체를 프로토타입이라고 함

다양한 방식으로 생성된 객체들의 잡합이 만들어지고, 설정과 비슷한 객체가 필요한 경우 새 객체 대신 프로토타입을 복제하고, 수정하면 됨

복사하는 객체들의 구상 클래스가 코드에 의존하면 안될 때 사용
각자 자신의 객체를 초기화하는 방식만 다른 자식클래스의 수를 줄이는 상황에서 좋음(공통 설정)
복제 메서드는 한 줄로 보통 구현됨
추가 옵션으로 자주 사용하는 프로토타입들의 카탈로그를 저장할 중앙 프로토타입 레지스터리가 가능함
정적 메서드는 검색 기준으로 찾고, 검색해서 생성해서 줌

장점은 구상 클래스에 결합하지 않고 복제 가능
반복되는 초기화 코드 제거
복잡한 객체 쉽게 생성
복잡한 객체 사전 처리시 상속 대신 사용 가능

단점은 순환참조가 너무 힘듦

프로토타입은 커맨드 패턴의 복사본을 기록에 저장해야 할 때 도움이 될 수 있음
데코레이터나, 복합체 패턴이 많으면 프로토타입이 종종 좋을 수 있음
상속 기반 단점이 없음
메멘토패턴의 대안이 될 수 있음

어댑터

서로 호환되지 않는 인터페이스를 가진 객체가 협업 가능하도록 만듦
어댑터는 변환의 복잡성을 숨기기 위해 객체중 하나를 래핑함
래핑된 객체는 어댑터를 인식할 수 없음
양방향 호출을 변환 가능한 어댑터를 만드는 것도 가능함

객체 합성의 방식을 사용함

클래스 어댑팅
다중 상속이 지원될 경우 양쪽을 모두 상속받아서 관리 메서드를 내에서 변하환하는 경우가 있음

어댑터 클래스는 기존 클래스를 사용하고 싶지만 나머지 코드와 호환되지 않을 때 사용
중간 레이어 클래스임
부모 클래스에 추가할 수 없는 기능이지만.
자식 클래스에 공통 기능이 있는 것을 재사용 하려는 경우에 사용해라

누락된 기능을 어댑터 클래스에 넣는다
누락된 기능이 있는 객체들을 래핑하면 필요한 기능들을 동적으로 얻을 수 있음
데코레이터와 유사함

호환되지 않는 인터페이스가 있는 클래스가 최소 2개 이상인지를 확인
클라이언트 인터페이스 선언 후 서비스와 통신하는 방식 기술

장점은 단일 책임 원칙. 변환 로직을 분리할 수 있음
개방 폐쇄 원칙. 어댑터 코드를 손상시키지 않고 새로운 어댑터 도입 가능

다수의 새로운 인터페이스와 클래스가 많아짐
서비스를 변경하는 것이 간단할 수 있음

브릿지는 사전에 설계. 앱의 다양한 부분을 독립적으로 개발할 수 있도록 함 반대로 어댑터는 기존 앱과 사용되어 원래 호환되지 않는 일부 클래스를 수정함

어댑터 : 기존 객체의 인터페이스를 변경하는 반면 데코레이터는 객체의 인터페이스를 변경하지 않고 향상한다. 데코레이터는 어댑터를 사용할 때는 불가능한 재귀적 합성도 지원함
어댑터는 다른 인터페이스, 프록시는 같은 인터페이스, 데코레이터는 향상된 인터페이스를 래핑된 객체에 제공함
퍼사드는 기존 객체들을 위한 새 인터페이스를 정의하는 반면
어댑터는 기존 인터페이스를 사용할 수 있도록 도와줌
어댑터는 하나의 객체, 퍼사드는 많은 객체의 하위 시스템과 함께 동작

브릿지, 상태, 전략 패턴은 유사함. 브릿지도 이와 유사함.
장점은 단순한 패턴이라는 것들로부터 알 수 있는 정보가 많아짐

브릿지 패턴

브리지는 큰 클래스 또는 밀접하게 관련된 클래스의 집합을 2개의 개별 계층 구조로 나눈 후 각자 독립적으로 개발할 수 있도록 하는 구조 디자인 패턴

간단하게 그래픽 ui <-> 운영체제가 있다고 했을 때
확장 방식은 여러 그래픽 인터페이스
여러 운영체제 지원이 가능함
이때 2방향을 모두 한 순간에 고려하면 경우의 수가 폭발함
이를 해결하기 위해 그래픽 하나/ 운영체제 를 각각 추상화 시켜서

와 같이 설정함

추상화는 상위 수준의 제어 논리 제공. 구현 객체에 의존해 실제 하위 수준 작업들을 수행한다
구현은 구상 구현들에 공통적인 인터페이스를 선언하며, 추상화는 여기에 선언된 메서드들을 통해서만 구현 객체와 소통할 수 있음

추상화는 구현과 같은 메서드 나열은 가능. 보통 구현이 선언한 원시 작업들에 의존하는 몇가지 복잡한 행동들을 선언
구상 구현에는 플랫폼별 코드가 포함됨
정제된 추상화들은 제어 논리의 변형을 제공함. 그들은 부모처럼 일반 구현 인터페이스를 통해 다른 구현들과 작업함
일반적으로 클라이언트는 추상화와 작업하는데만 관심이 있음 그러나 추상화 객체를 구현 객체중 하나와 연결하는 것도 클라이언트의 역할

모놀리식 클래스를 나누고 정동할 때 유용함
클래스가 다양한 데이터베이스 서버들과 작동할 수 있는 경우
브릿지 패턴시 모놀리식 클래스를 여러 클래스 계층 구조로 나눌 수 있음
각 계층 구조의 클래스들을 다른 계층구조들에 있는 클래스들과는 독립적으로 변경할 수 있다.
이 접근 방식은 코드의 유지관리를 단순화하고 기존 코드가 손상될 위험을 최소화 시킴

여러 독립 차원에서 클래스를 확장할 때 사용
런타임에 구현을 전환할 수 있어야 할 때 사용.( 브릿지와 전략패턴과 비슷하게 오해받도록 하는 것)
필드에 객체만 바꿔 끼면 됨

패턴은 클래스의 구조를 설계하는 그 이상의 것. 문제 및 의도에 대해서도 소통이 가능함
장점
플랫폼 독립적으로 작동 가능
클라이언트 코드는 상위 수준의 추상화 통해 작동. 세부 정보에 노출 안됨
개방/폐쇄 원칙. 새로운 추상화들과 구현들을 상호 독립적으로 도입할 수 있다.
단일 책임 원칙. 추상화의 상위 수준 논리와 구현으 플랫폼 세부정보에 집중할 수 있음

결합도가 높은 경우 더 복잡해질 수 있음
브릿지는 보통 사전에 설계됨. 독립적으로 개발을 목적으로 함
브릿지, 상태, 어댑터는 모두 유사함. 모든 패턴은 다른 객체에 작업을 위임하는 합성을 기반으로 함
이 패턴들은 모두 다른 문제들을 해결함
패턴은 특정 방식으로 코드를 짜는 레시피일 뿐.
추상 팩토리 + 브릿지도 가능함
브릿지에 의해 정의된 어떤 추상호들이 특정 구현들과만 작동할 수 있는 경우 유용
빌더 + 브릿지도 가능함
디렉터 클래스는 추상화의 역할을 하고, 다양한 빌더는 구현의 역할을 함

복합체

복합체는 앱의 핵심 모델이 트리로 표현 가능할 때만 사용해야 하지만
composite 으로 담는 것이 핵심이 아니라 모두에게 공통적인 작업을 할당하고 그 작업을 모아주는 것이 핵심이 됨

장점 : 재귀적으로 관리할 수 있어서 OCP가 잘 지켜짐
복잡한 트리 구조가 동일하게 작동하는 것처럼 보여서 간단함

단점 : 너무 일반화 시켜버리거나, 일이 다른 경우도 많음

이때 빌더를 사용할 수 있다
(addChild 라면 복합체를, 아니라면 leaf를 보낸다)
iterator를 사용해서 순회도 가능함
책임 연쇄 패턴을 사용할 수 있음

profile
학생의 마음가짐으로 최선을 다하자

0개의 댓글