🥕
TIL
  • [TIL] Studying tech / computer science knowledge
  • KeyMap
  • 알고리즘
    • 복잡도 계산 ( Computational Complexity )
    • DisjointSet-unionFind
    • Bellman-ford Algorithm
    • Dijkstra's Algorithm
    • DP ( Dynamic Programming , 동적 계획법 )
    • 플로이드-워셜 알고리즘 (Floyd-Warshall algorithm)
    • Kruskal's Algorithm
    • 최장 증가 수열 (Longes Increasing Subsequence)
    • Prim's Algorithm
    • 정렬
    • 시간복잡도 와 공간복잡도 ( Time Complexity & Space Complexity )
    • Topological Sort (위상 정렬)
  • 책 읽고난 후 요약
    • 프로그래밍 대회에서 배우는 알고리즘 문제해결 전략
    • cleancode
    • 도메인 주도 설계로 시작하는 마이크로서비스 개발
    • 오브젝트
  • CDC
    • debzium
    • kafka
  • 개발 상식
    • asciidoctor
    • 컴파일러
    • ELK 스택
    • 엔디안
    • git
    • Gitmoji
    • 테스트 종류
    • 라이브러리와 프레임워크
    • 정규 표현식
    • REST API
    • 동기와 비동기 / Blocking과 NonBlocking
    • Transaction Script와 Domain Model
    • 디자인 패턴
      • 행동 패턴
      • 객체 생성 패턴
        • 추상 팩토리 패턴
        • 빌더 패턴
        • 팩토리 메서드 패턴
        • [생성 패턴] 프로토 타입 (Prototype Parttern)
        • 싱글톤
      • 구조 패턴
        • 어댑터 패턴
        • 브릿지 패턴
        • 컴포짓(Composite) 패턴
        • 데코레이터
        • 프록시
    • refactoring
      • 중복 코드
      • 전역 데이터
      • 긴 함수
      • 긴 매개변수 목록
      • 가변 데이터
      • 이해하기 힘든 이름
  • 자료구조
    • AVL Tree
    • Splay Tree
    • aaTree
    • array-list
    • 자료구조 시간/공간 복잡도
    • 그래프
    • 힙
    • Red Black Tree
    • stack-queue
    • 트리 ( Tree )
  • DevOps
    • MSA
    • Kubernetes
      • AccessingAPI
      • controller
      • dashboard
      • kubernetes
      • object
      • pod
      • service
      • volume
  • Java
    • 어노테이션
    • 제어문
    • 데이터 타입
    • Enum
    • jvm
    • 연산자
    • thread
    • Java8
      • CompletableFuture
      • Date/Time
      • 어노테이션과 메타스페이스
      • 인터페이스
      • 람다식
      • Optional
      • 스트림
  • JavaScript
    • moduleProject
    • webpack-babel
    • 코어 자바스크립트
      • array
      • 함수 바인딩
      • 데코레이터와 포워딩
      • Class
      • 비교 연산자
      • Date 내장 객체
      • destructuring-assignment
      • function
      • 함수의 prototype 프로퍼티
      • 가비지 컬렉션 ( Garbage Collection )
      • JSON (JavaScript Object Notation)
      • map-set
      • 내장 프로토타입
      • new연산자와 생성자 함수
      • 객체
      • Object.keys, values, entries
      • 옵셔널 체이닝 '?.'
      • 프로퍼티 플래그
      • 프로퍼티 종류
      • 프로토 타입
      • 호출 스케줄링 ( scheduling a call )
      • scope
      • this
      • type-conversions
      • type
      • 함수의 자료형
      • var_let_const
  • Linux
    • 기본 명령어
    • 파일 종류
    • 리눅스
  • 네트워크
    • 응용 계층 ( Application Layer )
    • 오류 검출과 오류 정정
    • Http
    • Http Header
    • 컴퓨터 네트워크란
    • 네트워크 계층
    • 네트워크 제어 영역
    • 전송 계층 ( Transport Layer )
  • PHP
    • Facade
    • composer
    • scopeResolutionOperator
    • Laravel
      • SocialProvider
      • architecture
      • blade
      • controller
      • db
      • dbArchitecture
      • debug
      • eloquent
      • email
      • event
      • exceptionHandling
      • middleware
      • model
      • modelFactory
      • pagingLoading
      • queryBuilder
      • route
      • scout
      • seeding
      • tntsearch
      • validate
      • view
  • React
    • Next.js
    • React 란?
  • Spring
    • Controller
    • 요청이 들어왔을때 스프링이 처리하는 방법 ( 내부구조 )
    • ConfigurationProperties
    • Entity / DTO / VO
    • Maven
    • Repository와 DAO
    • 스프링 빈
    • Spring Framework
    • MVC 패턴
    • 도메인 입력값 검증
    • Spring Cloud
      • Spring Cloud
      • Eureka
    • Spring Data
      • JPA
      • JPA 어노테이션
      • 엔티티 비교
      • 복합 키와 식별 관계 매핑
      • JPA 예외처리
      • 객체지향 쿼리
      • EntityManagerFactory와 EntityManager
      • JPA 최적화
      • 프록시와 연관관계 맵핑
      • 연관관계
      • 상속관계 맵핑
      • 트랜잭션 범위와 영속성 컨텍스트
      • 데이터 타입
      • MySQL 연결
      • Pageable
    • Spring Project들과 library
      • Custom Serialize
      • Elasticsearch Index API
      • Spring HATEOAS
      • lombok (롬복)
      • Model Mapper
      • Object Mapper
      • Representation Model
      • Spring REST Docs
      • Spring Boot
    • Spring Security
      • Spring Security
      • Authentication
      • Authentication Filter
      • Authorization Filter
      • Filter Chain
      • SecurityContext
      • Spring OAuth2.0
    • Spring Test
      • AssertJ
      • Junit5
      • JunitParams
      • Mock Object
  • DataBase
    • ALIAS
    • CONCAT
    • CTE
    • Group By
    • HAVING
    • IFNULL
    • 인덱스
    • JOIN
    • ORDER BY
    • ROLLUP
    • SELECT
    • SELECT DISTINCT
    • SQL
    • WHERE
  • Web 상식
    • OAuth
    • WAS
    • HTTP통신 기반 인증
    • 브라우저
    • CSR 과 SSR
    • HTTPS
    • Web
Powered by GitBook
On this page
  • 적용전 코드
  • Bridge 패턴 적용후 코드
  • 장점
  • 적용가능한 경우
  • 어댑터패턴과의 차이점
  1. 개발 상식
  2. 디자인 패턴
  3. 구조 패턴

브릿지 패턴

구현부분에서 추상적인 부분과 구현 부분을 분리하여 서로 독립적으로 변경/확장이 가능하게 하는 패턴

적용전 코드

//외부 APi
public class KakaoMapApi{
    public void drawMap(int x,int y){
        System.out.println("카카오는 " + x + "와 " + y + "로 지도를 그립니다.");
    }
}

public class NaverMapApi {
    Integer x;
    Integer y;

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public void sketchMap(){
        if(x == null || y == null) throw new NullPointerException("x와 y는 null일 수 없습니다.");
        System.out.println("네이버는 " + x + "와 " + y + "로 지도를 그립니다.");
    }
}

//구현체
public abstract class MapPage {
    protected final int x;
    protected final int y;
    protected final KakaoMapApi mapApi = new KakaoMapApi();


    public MapPage(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public abstract void drawPage();
}

public class MyMapPage extends MapPage {
    public MyMapPage(int x, int y) {
        super(x,y);
    }

    public void drawPage(){
        System.out.println("나의 페이지에 지도 그리기");
        Systme.out.println("카카오 맵 이용");
        mapApi.drawMap(x,y);
    }
}

나의 페이지를 그리기 위해 외부 api를 사용하는데 이때 kakaoMapApi와 NaverMapApi가 임의로 저런 형태로 존재한다고 가정을 해보겠습니다. 이때, 두 api는 맵을 그리는 방식도 제공하는 메서드도 사용방법도 다릅니다.

페이지에서 Kakao api를 이용하여 지도를 포함한 페이지를 그리려고 하는데 만일 kakao api가 자주 끊긴다는 소식을 듣고 naver api도 이용하도록 바꾸려고 한다면 아래와 같이 기존 MyMapPage를 수정하고 이를 상속받는 모든 구현체들의 drawPage()를 수정해주어야 할 것입니다.

또한, 새로운 api가 등장하여 교체하거나 기존 api의 사용방법이 바뀐다면 그때마다 계속 수정이 일어나게 될 것입니다.

public abstract class MapPage {
    protected final int x;
    protected final int y;
    protected final NaverMapApi mapApi = new NaverMapApi();
    protected final KakaoMapApi mapApi = new KakaoMapApi();


    public MapPage(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public abstract void drawPage(String api);
}

public class MyMapPage extends MapPage {
    public MyMapPage(int x, int y) {
        super(x,y);
    }

    public void drawPage(String api){
        if("kakao".equals(api) ){
            System.out.println("나의 페이지에 지도 그리기");
            Systme.out.println("카카오 맵 이용");
            mapApi.drawMap(x,y);
        }else if( "naver".equals(api) ){
            System.out.println("나의 페이지에 지도 그리기");
            Systme.out.println("네이버 맵 이용");
            mapApi.setX(x);
            mapApi.setY(y);
            mapApi.sketchMap();
        }
    }
}

Bridge 패턴 적용후 코드

기존 코드에서 api를 이용하여 지도를 그리는 구현부분을 별도의 인터페이스로 분리하고 클래스에서 이 추상적인 인터페이스를 사용하도록하여 종속관계를 피하고 결합도를 낮추어 구현부분에 해당하는 객체의 범용성을 높이도록 설계를 해보자.

//구현부
public interface MapApi {
    public void drawMap(int x, int y);
}

public class MyNaverMapApi implements MapApi{
    private final NaverMapApi mapApi = new NaverMapApi();

    @Override
    public void drawMap(int x, int y) {
        mapApi.setX(x);
        mapApi.setY(y);
        mapApi.sketchMap();
    }
}

public class MyKakaoMapApi implements MapApi{
    private final KakaoMapApi mapApi = new KakaoMapApi();

    @Override
    public void drawMap(int x, int y) {
        mapApi.drawMap(x,y);
    }
}

//추상층
public abstract class MapPage {
    protected final int x;
    protected final int y;
    protected final MapApi mapApi;

    public MapPage(int x, int y,MapApi mapApi) {
        this.x = x;
        this.y = y;
    }

    public abstract void drawPage();
}

//구현체
public class MyMapPage implements MapPage{
    public MyMapPage(int x, int y,MapApi mapApi) {
        super(x,y,mapApi);
    }

    public void drawPage(){
        System.out.println("나의 페이지에 지도 그리기");
        mapApi.drawMap(x,y);
    }
}

//Client
public class Client {
    public static void main(String[] args) {
        double x = 20.1234;
        double y = 1.35452;
        MyPage page1 = new MyPage(x,y,new MyNaverMapApi());
        page1.drawPage();   //나의 페이지에 지도 그리기
                            //네이버는 20.1234와 1.35452로 지도를 그립니다.

        MyPage page2 = new MyPage(x,y,new MyKakaoMapApi());
        page2.drawPage();   //나의 페이지에 지도 그리기
                            //카카오는 20.1234와 1.35452로 지도를 그립니다.
    }
}

기존에는 외부 api에 따라 map을 그리는 방식이 MapPage에 종속되어 외부객체에서는 접근이 불가능했다면, 브릿지패턴을 통해 설계를 진행한다면 MapPage뿐만이 아닌 다른 객체에서도 외부 api에 맞게 map을 그리는 메서드에 접근이 가능해 얼마든지 결합을 할 수 있다.

장점

  1. 확장에 유연

  2. 단일 책임의 원칙을 지키며 설계가 가능

  3. 런타임에 기능(구현부)를 변경이 가능

적용가능한 경우

  • 런타임에 구현부를 결정하려는 경우

  • 구현부분과 추상부분을 독립적으로 변경가능하게 하려는 경우

  • 여러 객체에서 구현부분을 공유하려고 하는 경우

Bridge 패턴은 구조설계에 속하는 패턴으로 코드를 통해서만 해당 패턴을 사용할 수 있는 것이 아니라 아래 사진처럼 시스템을 설계하는데 있어서도 볼 수 있다.

어댑터패턴과의 차이점

객체를 입력으로 받아 해당 객체와 연관된 새로운 클래스나 인터페이스를 참조한다는 점에서는 동일

어댑터 패턴은 서로 다른 인터페이스를 연결해줌으로써 시스템의 설계가 완료된후에 적용할 수 있지만 브릿지패턴은 설계를 진행중에 의도적으로 확장을 고려하여 추상/구현부(두 레이어)로 분리하여 이를 연결시켜주는 패턴

한마디로 말하면 사용 목적이 다른데 어댑터 패턴의 서로 다른 인터페이스를 연결해주는 것이 목적이고, 브릿지 패턴은 구현부분을 별도로 분리하여 객체들의 범용성을 증가시키기고 계층간의 결합도를 낮추는것이 목적

Previous어댑터 패턴Next컴포짓(Composite) 패턴

Last updated 3 years ago

bridge