일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 회사폐업
- IT기초
- 취업사실신고
- HeadFirstDesignPatterns
- 알고리즘
- 자료구조
- 네트워크
- 정보
- 생애첫계약
- 부분합알고리즘
- 실업급여
- 실업인정인터넷신청
- 프로그래머스
- 청년내일채움공제
- C++
- 튜터링
- 후니의쉽게쓴시스코네트워킹
- 전화영어
- 캡쳐링
- 코딩테스트
- 순열
- 모여봐요동물의숲
- 후니의쉽게쓴시스코라우팅
- leetcode
- array
- 정보처리기사개정
- 막대기자르기
- 동적계획법
- 사회초년생
- 자취준비
- Today
- Total
따봉도치야 고마워
Head First Design Patterns : (7)어댑터 패턴과 퍼사드 패턴 본문
어댑터 패턴
- 한 클래스의 인터페이스를 다른 클라이너트에서 사용하고자 하는 다른 인터페이스로 변환한다.
- 어탭터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 사용 가능.
- 클라이언트는 타겟 인터페이스에 맞게 구현이 되어있고, 그걸 통해 메소드 호출
- 어댑터는 타겟 인터페이스를 구현하며 *어댑티 객체를 가지고 있음
- 어댑터는 어댑티 객체를 사용해 클라이언트의 요청을 응답
- 클라이언트는 결과를 받지만 중간에 어댑터가 껴있는지 알지 못함
*어댑티 : 어댑터를 가운데 두고 클라이언트(타겟 인터페이스)와 반대의 위치에 있는 것 ex) 아래 예제에서 Turkey
객체지향 어댑터
- 말 그대로, 어떤 인터페이스를 클라이언트가 요구하는 형태의 인터페이스에 적응 시켜주는 역할
ex) 기존 시스템에 새로운 클래스 라이브러리를 사용해야하는데, 둘의 인터페이스가 다른 경우
- 기존 코드들을 수정하지 않고 어댑터를 이용해 사용
예제
- Duck, Turkey 인터페이스를 생성
public interface Duck{
public void quack();
public void fly();
}
public interface Turkey{
public void gobble(); //골골거리면서 욺
public void fly(); //날 수 있지만 멀리 날아가진 못함
}
- Duck객체가 모잘라 Turkey 객체를 대신 사용해야하는 상황
- 바로 사용할 수 없으니 : TurkeyAdapter 생성
//변환할(적응시킬) 인터페이스를 구현
public class TurkeyAdapter implements Duck{
Turkey turkey;
//원래 형식의 객체에 대한 레퍼런스 저장
public TurkeyAdapter(Turkey turkey){
this.turkey = turkey;
}
public void quack(){
turkey.gobble();
}
public void fly(){
for(int i=0; i<5; i++){ //오리처럼 멀리 날 수 있도록 여러번 호출
turkey.fly();
}
}
}
- 위처럼 어댑터를 만들면 Duck 객체에 Turkey 객체를 넣을 수 있음
WildTurkey turkey = new WildTurkey(); //Turkey인터페이스를 구현한 클래스 객체
Duck turkeyAdapter = new TurkeyAdapter(turkey);
클래스 어댑터란?
- 어댑터엔 객체 어댑터와 클래스 어댑터가 있음 (위에 내용들은 객체 어댑터)
- 클래스 어댑터 형식으로 구현하려면 다중 상속이 필요하기 때문에 자바에선 불가능
- 객체 어댑터는 구성을 통해 어댑티에 요청 전달을 하지만, 클래스 어댑터에선 타겟/어댑티 클래스 둘 모두를 상속 받는 서브 클래스를 만들어 요청 처리
|
Ojbect Adapter |
Class Adapter |
장점 |
상속이 아닌 구성(Composition)을 사용해 더 유연함 |
Adaptee 전체를 재구현하지 않아도 되고, Adaptee의 행동을 오버라이드 할 수 있음 Adaptee 객체를 만들지 않아도 됨 |
단점 |
Adaptee 객체를 만들어야 사용가능 |
상속을 이용하기 때문에 특정 Adatee 클래스에만 적용가능 다중상속이 지원되는 언어에서만 사용가능 |
퍼사드 패턴
- 어떤 서브시스템의 일련의 인터페이스에 대한 통합된 인터페이스를 제공한다
- 퍼사드에서 고수준 인터페이스를 정의하기 때문에 서브 시스템을 더 쉽게 사용할 수 있음.
ex) '복잡한 서브 시스템과 분리' :: 홈 씨어터
- 영화를 보기 위해 light.on > movie.on .. 처럼 여러 서브 시스템을 일일히 제어하는 게 아니라
- 퍼사드 클래스를 하나 생성해 놓고 watchMovie() 안에서 위의 서브 시스템 제어를 명시해 놓고 클라는 해당 메소드만 호출하는 것
디자인 원칙
- 최소 지식 원칙 (=데메테르의 법칙, Law of Demeter) - 정말 친한 친구하고만 얘기해라
- 객체 간의 상호작용을 줄이는 4가지 가이드라인 : 다음 4 종류 객체의 메소드만 호출
- 객체 자체
- 메소드에 매개변수로 전달된 객체
- 해당 메소드에서 생성하거나 인스턴스를 만든 객체
- 그 객체에 속하는 구성요소 (자신이 가지고 있는)
- 왜? 어떤 메소드를 호출한 결과로 리턴받은 객체에 있는 메소드를 호출하는 것 -> 직접 알고 있는 객체의 수가 늘어 남
- 그 객체 쪽에서 대신 요청을 하도록 만들어야 함.
//1.가이드라인을 따르지 않은 경우
public float getTemp(){
Thermometer thermometer = station.getThermometer();
return thermometer.getTemperature();
//station으로 부터 Thermometer 객체를 받아 해당 객체의 메소드를 직접 호출
}
//2.가이드라인을 따른 경우
public float getTemp(){
return station.getTemperature();
//station 클래스에 thermometer에 요청을 해주는 메소드를 추가해 의존하는 클래스 개수 줄임
}
데코레이터 패턴 vs 어댑터 패턴 vs 퍼사드 패턴
- 셋 다 클라이언트 코드를 고치지 않고 특정 동작을 수행
- 데코레이터 : 객체의 행동/책임을 추가
- 어댑터 : 인터페이스를 변환
- 퍼사드 : 일련의 행동을 감싸서 단순화
Q&A
1. (어댑터) 대형 타겟 인터페이스를 구현해야하는 경우 할 일이 매우 많아지지 않나
맞음. 하지만 기존 코드를 새 인터페이스에 맞춰 고치는 것보다 변동 사항을 캡슐화한 하나의 클래스를 제공하는 법이 나음
2. (퍼사드) 최소 지식 원칙의 단점은?
다른 구성요소에 대한 메소드 호출을 처리하기 위해 '래퍼' 클래스를 생성해야 해, 시스템이 더 복잡해지고 개발 시간/성능이 안좋아 질 수 있음.
'프로그래밍 > 공부' 카테고리의 다른 글
Head First Design Patterns : (9)이터레이터와 컴포지트 패턴 (0) | 2020.09.24 |
---|---|
Head First Design Patterns : (8)템플릿 메소드 패턴 (0) | 2020.09.23 |
Head First Design Patterns : (6)커맨드 패턴 (0) | 2020.09.17 |
Head First Design Patterns : (5)싱글턴 패턴 (0) | 2020.09.15 |
Head First Design Patterns : (4)팩토리 패턴 (0) | 2020.09.14 |