22/12/11

송은우·2022년 12월 11일
0

TIL

목록 보기
47/61

https://loosie.tistory.com/349
백준 2504 문제
꼭 안쪽에서 처리할 필요 없이 바깥에서 분배법칙처럼 접근할 수도 있었음

데코레이터

객체의 동작을 변경하기 시작하는 방식으로 가장 빨리 생각하는 것은 상속임
단 상속은 런타임에 방식을 변경할 수 없음
하나의 부모 클래스만 가질 수 있음

같은 인터페이스이기만 한다면 다른 데코레이터를 참조하던, 진짜 원래 객체를 참조하던 관계가 전혀 없음

옷을 입는 과정과 비슷함. 티셔츠를 여러개 입거나, 잠바를 입는 것은 쉽게 벗을 수 잇음

장점
상속과 무관하게 확장할 수 있음
런타임에 책임을 추가, 삭제 할 수 있음
행동 합성 가능
단일 책임 원칙을 확실히 지킬 수 있음

단점
순서에 의존하게 됨
특정 래퍼만을 제거하기 쉽지 않아짐
초기 설정 코드가 보기 흉할 수 있음

어댑터는 기존 객체의 인터페이스를 변경함. 데코레이터는 객체의 인터페이스를 유지함
어댑터는 다른 인터페이스 프록시는 같은 인터페이스 데코레이터는 향상된 인터페이스를 제공됨
책임 연쇄와 데코레이터 사이에는 차이가 있음
책임연쇄 핸들러는 독립적으로 임의의 작업을 실행할 수 있음, 중단도 가능함
데코레이터는 흐름을 중단할 수 없음

복합체와 데코레이터 간의 차이는 데코레이터는 자식이 하나뿐, 복합체는 여러개 가능
데코레이터와 복합체가 많은 경우 프로토타입 패턴이 유리할 수 있음
데코레이터는 바깥을 변경하고, 전략은 내부에서 변경함
데코레이터와 프록시의 의도가 다름
프록시는 자체적으로 서비스 객체의 수명을 관리할 수 있고, 데코레이터는 클라이언트가 다 관리함

synchronized 같은 것들이 예시임

퍼사드 패턴

복잡한 하위시스템에 대한 제한적이지만 간단한 인터페이스가 필요한 경우 사용
하위 시스템을 계층적으로 구성하고 싶을 경우에 사용하는 것이 좋음
기존 하위시스템이 제공하는 모든 기능을 다 쓰지는 않는 경우에 특히 유용함

단점은 모든 것을 아는 전지전능한 객체가 되어버릴 수 있음
보통 라이브러리와 연결 과정을 추상화 하는 경우가 많음
퍼사드는 새로운 인터페이스, 어댑터는 많은 하위 시스템과 함께 작동
추상 팩토리는 생성 부분만 숨기고 싶을 때 사용, 퍼사드는 사용 자체를 숨기고 싶을 때 사용
플라이웨이트는 작은 객체를 여러개, 퍼사드는 하나의 큰 단일 객체
퍼사드는 신 기능을 도입하지는 못하지만, 중재자는 시스템 컴포넌트 단위의 통신을 관리함
퍼사드와 프록시가 유사함
퍼사드는 일부만 나타낸다는 점에서만 차이가 있음
퍼사드는 종종 싱글턴으로 변경되기도 함

플라이웨이트

객체 속에서 고유한 객체가 엄청 많이 사용될 때
대표적인 사례로 Boolean 도 있을 수 있음
매번 생성하는 것이 아닌 Boolean을 2개만 미리 만들어 두고, 거기서 바로 반환하는 것처럼
고유한 상태를 어마어마하게 많이 만드는 것이 아닌 저장해서 캐싱하는 것
많은 수의 객체를 사용해야 해서 램을 거의 다 사용했을 경우에만 사용하는 것을 권장
근본적인 해결책 보다는 최적화에 더 가까움
유사 객체가 많고, 중복된 상태가 공유될 때 사용함
단 setter가 있으면 동기화 문제가 발생할 수 있음
보통 팩토리 클래스를 통해 관리하는 경우가 많음

코드가 복잡해지기에 이해하기 힘들 수 있음
계산 과정이 복잡하다면 CPU가 낭비될 수 있음
램 절약을 위해 플라이 웨이트 패턴으로 복합체의 leaf를 대체할 수 잇을 수 있음
플라이웨이트는 작은 객체 여러개, 퍼사드는 하나의 단일 객체 많이

싱글턴은 하나만, 플라이웨이트는 많은 객체
싱글턴은 mutable, 플라이웨이트는 거의 무조건 immutable

프록시

같은 인터페이스를 사용함
전, 후에 뭔가 일을 하기 원하는 경우에 보통 많이 사용함

지연 초기화
접근 제어(권한 검증이 있는 경우)
원격 서비스의 로컬 실행
로깅
캐싱
클라이언트가 참조했는지 여부도 볼 수 있음

클라이언트들이 알지 못하는 상황에서 제어 가능함
OCP도 지켜짐
서비스 객체가 준비되지 않아도 실행 가능

코드 복잡해질 수 있고, 로딩 시간이 있을 수 있음
데코레이터와 프록시의 구조는 비슷하나 이들의 의도는 매우 다릅니다. 한 객체가 일부 작업을 다른 객체에 위임해야 하는 합성 원칙을 기반으로 합니다. 이 두 패턴의 차이점은 프록시는 일반적으로 자체적으로 자신의 서비스 객체의 수명 주기를 관리하는 반면 데코레이터의 합성은 항상 클라이언트에 의해 제어된다는 점입니다.

책임 연쇄

어떤 순서로 적용될 지는 모르지만
원하는 순서대로 접근하도록 하는 방식
express의 middleware
런타임에 순서가 바뀔 수 있어야 하는 것

처리 순서 제어, 단일 책임, 개방 폐쇄가 지켜짐
일부 요청은 처리가 안 될 수 있음
커맨드, 중재자, 옵저버 등은 수신자와 발신자 사이에 관계를 제어함
책임 연쇄는 종종 복합체와 함께 수행됨
책임연쇄는 중간에 멈출 수 있고, 데코레이터는 멈추면 안됨

커맨드

요청을 요청에 대한 정보가 주어졌을 때 독립적으로 실행할 수 있는 독립 실행형 객체로 바꾸는 것
요청을 인수화 하는 것이 가능하다는 것
대기열에 넣을 수도 있고
중간에 대기열에서 뽑아서 취소할 수도 있다는 것이 장점임
발송자 클래스(invoke 클래스)가 커맨드 객체에 대한 참조를 가지고 있을 수 있어야 함
커맨드 객체를 생성할 책임은 없음. 시작은 보통 클라이언트로부터 시작됨

작업을 객체의 매개변수 역할로 할 필요가 있다면 사용하는 것이 좋음
작업의 실행을 예약하거나, 원격으로 할 때가 좋음
되돌릴 수 있는 작업일 경우에 좋음

단일책임, ocp, 실행취소, 지연 실행, 간단한 커맨드의 집합을 복잡한 커맨드로 바꿀 수 있음

발송자와 수신자 사이에 한 레이어가 더 붙었기에 복잡해짐
책임 연쇄의 핸들러들을 커맨드로 바꿀 수 있음

커맨드는 모든 작업을 객체로 변환하는 것이고
전략 패턴은 같은 작업을 실행하는 알고리즘을 바꾼다

프로토타입은 커맨드를 복제할 때 도움이 될 수 있음

java의 Runnable과 비슷함
작업 자체가 하나의 객체가 됨
execute를 호출하면 그게 끝임

반복자

요소들의 기본 표현을 노출하지 않고 순회할 수 있도록 도와줌
순서가 중요한 경우가 생각보다 크지 않았음
현재 위치, 남은 요소들을 다 캡슐화 해서
여러 반복자가 독립적으로 동시에 다른 컬렉션을 통과할 수 있음

같은 클라이언트 코드로 다른 컬렉션을 통과시킬 수 있다는 점이 중요함
반복자 중간에 권한 검증을 갖도록 할 수도 있음
구조의 복잡성을 숨기고 싶을 때 사용 가능
순회 코드를 단순하게 만들 수가 있음

단일책임
ocp
같은 컬렉션을 병렬 순회가 가능함
순회 지연이 가능함

직접 순회보다 비효율적이기도 함
단순 순회일 경우 반복자까지 적용하는 것이 과할 수 있음

반복자로 복합체를 순회할 수 있음
팩토리 + 반복자를 쓰면서 자식 클래스들이 해당 클래스의 컬렉션과 호환되도록 만들 수 있음
메멘토로 롤백이 가능함
비지터로 클래스가 모두 달라도 어떤 작업을 실행할 수 있다
반복자로 지연 로딩이 가능하다

중재자

서로서로 바로바로 연결하는 것들이 생각보다 많은 문제를 일으킬 수 있고, 복잡도를 너무 높일 수 있는데
이런 부분을 중간에서 모두 다 관리해버림

관제탑의 예시
모든 비행기들에 대해서 다 물어보는 것이 아닌, 관제탑하고만 통신함

클래스들이 서로 단단하게 결합될 때 쪼개는 것이 중요함
컴포넌트끼리 재사용을 도와줌
거의 유사한 객체가 재사용을 위해서 반복해서 사용될 때 사용하는 것을 추천함

단일 책임 원칙
OCP
결합도를 낮출 수 있음
개별 컴포넌트 재사용이 가능해짐

중재자가 전지전능한 객체가 될 수 있음
중재자는 퍼사드와 비슷한 역할을 함
퍼사드는 하위 시스템간에 자유로운 통신이 있고, 단순화된 인터페이스가 있음
중재자는 하위 시스템이 서로를 모름
중재자는 옵저버와 되게 비슷해질 수 있음
중재자가 하위 시스템을 다 아는데, 중재자가 콜백을 받으면 옵저버랑 거의 똑같이 작동할 수 있음
중재자는 여러 방식이 될 수 있음을 생각해야됨

이벤트를 특정 함수를 호출하는 방식으로 보통 구현을 많이 함
데이터 결과물이 중간으로 감
MVC의 컨트롤러가 중재자의 역할을 함

public interface Mediator {
    void addNewNote(Note note);
    void deleteNote();
    void getInfoFromList(Note note);
    void saveChanges();
    void markNote();
    void clear();
    void sendToFilter(ListModel listModel);
    void setElementsList(ListModel list);
    void registerComponent(Component component);
    void hideElements(boolean flag);
    void createGUI();
}

이런 느낌의 코드가 되어버림

메멘토는 전체 데이터를 스냅샷 해서 저장해둠
프로토타입 같은 패턴을 통해서 복사를 하고, 스냅샷을 저장하게 된다면 외부 캡슐화를 깨지 않을 수 있다

원래 객체 상태가 아닌 부가 메타데이터를 갖고 있는다
케어테이커 라고하는 객체 안에 ㅁ멘토 저장 가능

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

0개의 댓글