반응형
Jake Seo
제이크서 위키 블로그
Jake Seo
전체 방문자
오늘
어제
  • 분류 전체보기 (715)
    • 일상, 일기 (0)
    • 백준 문제풀이 (1)
    • 릿코드 문제풀이 (2)
    • 알고리즘 이론 (10)
      • 기본 이론 (2)
      • 배열과 문자열 (8)
    • 데이터베이스 (15)
      • Planet Scale (1)
      • MSSQL (9)
      • 디비 기본 개념 (1)
      • SQLite 직접 만들어보기 (4)
    • 보안 (7)
    • 설계 (1)
    • 네트워크 (17)
      • HTTP (9)
      • OSI Layers (5)
    • 회고 (31)
      • 연간 회고 (2)
      • 주간 회고 (29)
    • 인프라 (52)
      • 도커 (12)
      • AWS (9)
      • 용어 (21)
      • 웹 성능 (1)
      • 대규모 서비스를 지탱하는 기술 (9)
    • 깃 (7)
    • 빌드 도구 (7)
      • 메이븐 (6)
      • 그레이들 (0)
    • Java (135)
      • 이펙티브 자바 (73)
      • 자바 API (4)
      • 자바 잡지식 (30)
      • 자바 디자인 패턴 (21)
      • 톰캣 (Tomcat) (7)
    • 프레임워크 (64)
      • next.js (14)
      • 스프링 프레임워크 (28)
      • 토비의 스프링 (6)
      • 스프링 부트 (3)
      • JPA (Java Persistence API) (5)
      • Nest.js (8)
    • 프론트엔드 (48)
      • 다크모드 (1)
      • 노드 패키지 관리 매니저 (3)
      • CSS (19)
      • Web API (11)
      • tailwind-css (1)
      • React (5)
      • React 새 공식문서 요약 (1)
      • HTML (Markup Language) (5)
    • 자바스크립트 (108)
      • 모던 자바스크립트 (31)
      • 개념 (31)
      • 정규표현식 (5)
      • 코드 스니펫 (1)
      • 라이브러리 (6)
      • 인터뷰 (24)
      • 웹개발자를 위한 자바스크립트의 모든 것 (6)
      • 팁 (2)
    • Typescript (49)
    • 리눅스와 유닉스 (10)
    • Computer Science (1)
      • Compiler (1)
    • IDE (3)
      • VSCODE (1)
      • IntelliJ (2)
    • 세미나 & 컨퍼런스 (1)
    • 용어 (개발용어) (16)
      • 함수형 프로그래밍 용어들 (1)
    • ORM (2)
      • Prisma (2)
    • NODEJS (2)
    • cypress (1)
    • 리액트 네이티브 (React Native) (31)
    • 러스트 (Rust) (15)
    • 코틀린 (Kotlin) (4)
      • 자바에서 코틀린으로 (4)
    • 정규표현식 (3)
    • 구글 애널리틱스 (GA) (1)
    • SEO (2)
    • UML (2)
    • 맛탐험 (2)
    • 리팩토링 (1)
    • 서평 (2)
    • 소프트웨어 공학 (18)
      • 테스팅 (16)
      • 개발 프로세스 (1)
    • 교육학 (1)
    • 삶의 지혜, 통찰 (1)
    • Chat GPT (2)
    • 쉘스크립트 (1)
    • 컴파일 (2)
    • Dart (12)
    • 코드팩토리의 플러터 프로그래밍 (4)
    • 플러터 (17)
    • 안드로이드 스튜디오 (1)
    • 윈도우즈 (1)
    • 잡다한 백엔드 지식 (1)
    • 디자인 패턴 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • MSSQL
  • Java
  • 메이븐 페이즈
  • Pre-rendering
  • 팩터리 메서드 패턴
  • try-with-resources
  • bean Validation
  • serverless computing
  • 도커공식문서
  • 객체복사
  • 러스트
  • 서버리스 컴퓨팅
  • 토비의 스프링
  • 작업기억공간
  • 자바스크립트 인터뷰
  • 자료구조
  • item8
  • 자바스크립트
  • next js app
  • prerendering
  • 디자인패턴
  • 스프링 검증
  • 싱글톤 패턴
  • Next.js
  • 프로그래머의 뇌
  • 이펙티브 자바
  • 싱글톤
  • 느린 쿼리
  • 자바스크립트 면접
  • 참조 해제
  • 자바 검증
  • 메이븐 라이프사이클
  • 이펙티브 자바 item9
  • 싱글턴
  • 플라이웨이트패턴
  • NEXT JS
  • 자바
  • 외래키 제약조건
  • 슬로우 쿼리
  • Javadoc 자바독 자바주석 주석 Comment
  • pnpm
  • item9
  • 메이븐 골
  • 추상 팩터리 패턴
  • 자바 디자인패턴
  • item7
  • rust
  • 빈 검증
  • 이펙티브자바
  • 알고리즘

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Jake Seo

제이크서 위키 블로그

브릿지 패턴 (Bridge Pattern) 이란?
Java/자바 디자인 패턴

브릿지 패턴 (Bridge Pattern) 이란?

2023. 2. 19. 01:11

브릿지 (Bridge) 패턴

  • 커다란 클래스 혹은 긴밀하게 연관된 클래스를 추상 부분과 구현 부분으로 쪼개어 나눈다.
    • 두 부분이 독립적으로 개발될 수 있다.
  • extend 보다 composition 을 적극 활용한다.

다이어그램으로 살펴보기

현실 예제

  • 컵을 판매하는 회사가 있다.
  • 컵의 재질은 플라스틱, 유리, 종이 등이 존재한다.
  • 컵의 색상은 빨간색, 파란색, 노란색, 초록색 등이 존재한다.
  • 컵을 클래스화 시켜서 자바 프로그램에 녹여넣고 싶은데, 어떤 방식이 좋을까?

상속 (extend) 을 통한 접근

  • 먼저 Cup 클래스를 만들었다.
  • 컵의 재질을 표현하기 위해서 Material 인터페이스를 추가했다.
  • Material 을 상속하는 Plastic, Glass, Paper 등을 만들었다.
  • 이를 이용해 Cup 에 Material 을 상속시켜 PlasticCup, GlassCup, PaperCup 등을 만들었다.
  • 이번엔 컵의 색상을 표현하기 위해서 Color 인터페이스를 추가했다.
  • Color 를 상속시켜 Red, Green, Blue 등을 만들었다.
  • PlasticCup 에 Red 를 상속시킨 RedPlasticCup, Green 을 상속시킨 GreenPaperCup 등을 성공적으로 만들어냈다.
  • 시간이 지날수록 새로운 색이 추가되고 새로운 재질의 컵이 탄생했다.
  • 상속 클래스가 수십개가 탄생했고, 새로운 재질과 색상이 나올 때마다 컵을 추가해야 한다.

사용 (composition) 을 통한 접근

  • Cup 클래스를 만드는 것까지는 동일하다.
  • Cup 에 Material 과 Color 인터페이스를 필드로 추가했다.
  • Material 과 Color 를 인자로 받는 생성자만 만들어주었다.
  • 이제 어떤 재질의 어떤 색상의 컵을 사용하더라도 더 이상 클래스를 추가할 필요는 없다.

사용을 통한 접근이 갖는 의미

  • Bridge 패턴은 사용을 통한 접근을 이용해 문제를 해결하려 한다.
  • 클래스를 별도의 계층으로 추출함으로써, 원래 클래스가 한 클래스 내의 모든 상태 및 동작을 갖지 않고 새 계층의 객체를 참조한다.

코드 예제

  • 멀티플랫폼을 지원하는 GUI 도구를 만들려고 한다.
  • Mac 운영체제와 Windows 운영체제의 버튼을 만들어야 한다.
  • 버튼의 요구사항은 아래와 같다.
    • 버튼에는 색상이 들어갈 수 있다.
    • 버튼을 클릭하면 실행될 이벤트를 줄 수 있다.

Button

public interface Button {
    void onClick();
}
  • Button 은 인터페이스로 클릭하면 실행되는 onclick 이벤트를 가지고 있다.

Color

public interface Color {
    String getColorCode();
}
  • Color 도 인터페이스로 색상의 색상코드를 이용해 버튼의 색을 칠한다.

Red

public class Red implements Color {
    @Override
    public String getColorCode() {
        return "FF0000";
    }
}
  • 빨간색을 구현한 것이다.

Blue

public class Blue implements Color {
    @Override
    public String getColorCode() {
        return "0000FF";
    }
}
  • 파란색을 구현한 것이다.

MacButton

public class MacButton implements Button{
    private final Color color;

    public MacButton(Color color) {
        this.color = color;
    }

    @Override
    public void onClick() {
        System.out.println("맥 버튼 클릭, 색상 컬러: " + color.getColorCode());
    }
}
  • 맥OS 에 사용되는 버튼을 만들었다.
    • 생성자에서 Color 를 받고, onClick 이벤트는 직접 구현하면 된다.

WindowsButton

public class WindowsButton implements Button{
    private final Color color;

    public WindowsButton(Color color) {
        this.color = color;
    }

    @Override
    public void onClick() {
        System.out.println("윈도우즈 버튼 클릭, 색상 컬러: " + color.getColorCode());
    }
}
  • windows 에도 동일한 버튼을 만들어보았다.

클라이언트에서 사용하기

public class Client {
    public static void main(String[] args) {
        Button macButton = new MacButton(new Red());
        Button windowsButton = new WindowsButton(new Blue());

        macButton.onClick(); // 맥 버튼 클릭, 색상 컬러: FF0000
        windowsButton.onClick(); // 윈도우즈 버튼 클릭, 색상 컬러: 0000FF
    }
}
  • 클라이언트는 두가지 플랫폼의 버튼을 자유로운 색상으로 마음껏 만들 수 있다.
  • 더 확장하여 OS 인터페이스를 만들어 필드에 넣을 수 있다.
  • onClick 도 Event 라는 인터페이스를 상속하는 onClickEvent 인터페이스를 만들어 상속하고 필드로 사용할 수도 있다.

예제에서 유의깊게 봐야하는 점

  • 단순히 WindowsButton 과 MacButton 이라는 클래스를 만들어 필드를 생성하고 구현한 것이 아니라, 공통으로 구현에 필요한 부분을 추상화하여 나누었다.
  • 어디든 Button 타입이 필요한 곳이면, WindowsButton 인지 MacButton 인지는 무관하게 두 구현체 중 아무거나 올 수 있게 되었다.
  • 최악의 케이스를 상정해보자면, WindwosRedButton, WindowsBlueButton, MacRedButton, MacBlueButton 과 같은 개별 클래스들이 탄생할 수도 있었다.
  • 다이어그램과 비교하자면, 예제의 Button 이 Abstraction 이 될 수 있다. Windows Button 은 Refined Abstraction 이다. Color 인터페이스는 Implementation 에 해당하고, Red 와 같은 실제 색상은 Concrete Implementation 에 해당한다.

브릿지 패턴의 장단점

장점

  • 추상적인 코드를 구체적인 코드 변경 없이도 독립적으로 확장할 수 있다.
    • WindowsButton 의 Color 를 더 늘리고 싶다면, Color 를 상속하는 클래스 하나만 더 만들어주어 주입하면 된다.
    • WindowsButton 클래스의 onClick() 메서드에서는 Color 인터페이스를 이용해서 코드를 변경할 일이 없다.
  • 추상적인 코드와 구체적인 코드를 분리할 수 있다.
    • 구조적인 틀을 작성해놓고, 자유롭게 구현 코드를 주입할 수 있다.

단점

  • 계층 구조가 늘어나 복잡도가 증가할 수 있다.
    • 단 하나의 클래스만 만들고 추후에 확장 가능성이 아예 존재하지 않는다면, 오히려 번거로운 작업이 될 수 있다.
    • 처음 보는 개발자는 코드를 파악하는데 어려움을 겪을 수도 있다.

자바와 스프링에서는 브릿지 패턴을 어떻게 이용하고 있을까?

JDBC

public class JdbcExample {
    public static void main(String[] args) throws ClassNotFoundException {
        Class.forName("org.h2.Driver");

        try (Connection conn = DriverManager.getConnection ("jdbc:h2:mem:~/test", "sa","")) {

            String sql =  "CREATE TABLE  ACCOUNT " +
                    "(id INTEGER not NULL, " +
                    " email VARCHAR(255), " +
                    " password VARCHAR(255), " +
                    " PRIMARY KEY ( id ))";

            Statement statement = conn.createStatement();
            statement.execute(sql);

//            PreparedStatement statement1 = conn.prepareStatement(sql);
//            ResultSet resultSet = statement.executeQuery(sql);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}
  • JDBC 는 DB 벤더에 상관없이 쿼리를 실행시키고, 실행시킨 쿼리에 대한 결과를 받을 수 있다.
  • 실제 DB 에 대한 구체적인 구현은 Class.forName() 에서 호출하는 org.h2.Driver 에 들어있다.
    • Driver 에는 Statement, PreparedStatement, ResultSet 등을 이용하는 코드가 들어있을 것이다.
  • 다른 벤더의 DB 를 사용한다고 해도 JDBC 를 이용하는 코드가 바뀌진 않을 것이다.

Slf4j

public class Slf4jExample {
    private static Logger logger = LoggerFactory.getLogger(Slf4jExample.class);

    public static void main(String[] args) {
        logger.info("hello logger");
    }
}
  • Slf4j 와 같은 것을 Logging Facade 라고 부른다.
  • 실제 logger 구현체가 아니라, 로깅에 사용되는 인터페이스이다.
    • 새로운 로깅 구현체를 넣어도 이 코드는 변하지 않는다.
      • log4j2, logback 등 다양한 구현체를 사용할 수 있다.
  • 보는 관점에 따라 브릿지 패턴으로 볼 수 있다.

스프링의 MailSender, PlatformTransactionManager

public class BridgeInSpring {
    public static void main(String[] args) {
        MailSender mailSender = new JavaMailSenderImpl();
        PlatformTransactionManager platformTransactionManager = new JdbcTransactionManager();
    }
}
  • 스프링의 PortableServiceAbstraction 에 다양한 예제가 있다.
  • MailSender 에는 JavaMailSenderImpl 과 같은 구현체를 넣을 수 있다.
    • 스프링에서 제공하는 구현체는 JavaMailSenderImpl 하나 뿐이지만, 우리가 얼마든지 새로 MailSender 를 구현해넣을 수 있다.
  • PlatformTransactionManager 는 JdbcTransactionManager, JpaTransactionManager 등을 구현체로 사용할 수 있다.
  • 어떤 구현체를 넣더라도 인터페이스를 이용하기 때문에 기존의 코드가 변하지 않는다.
public class TransactionTemplate extends DefaultTransactionDefinition
        implements TransactionOperations, InitializingBean {

    /** Logger available to subclasses. */
    protected final Log logger = LogFactory.getLog(getClass());

    @Nullable
    private PlatformTransactionManager transactionManager;
  // ...
}
  • TransactionTemplate 에서 PlatformTransactionManager 를 사용하고 있다.
반응형
저작자표시 비영리 (새창열림)

'Java > 자바 디자인 패턴' 카테고리의 다른 글

데코레이터 패턴 (Decorator Pattern) 이란?  (0) 2023.02.25
컴포지트 패턴 (Composite Pattern, 컴포짓 패턴) 이란?  (0) 2023.02.20
자바 디자인 패턴, 객체 생성 관련 패턴 (Object Creational Patterns) 이란?  (0) 2023.02.17
어댑터 패턴 (Adapter Pattern) 이란?  (1) 2023.01.29
프로토타입 패턴 (Prototype Pattern) 이란?  (2) 2023.01.28
    'Java/자바 디자인 패턴' 카테고리의 다른 글
    • 데코레이터 패턴 (Decorator Pattern) 이란?
    • 컴포지트 패턴 (Composite Pattern, 컴포짓 패턴) 이란?
    • 자바 디자인 패턴, 객체 생성 관련 패턴 (Object Creational Patterns) 이란?
    • 어댑터 패턴 (Adapter Pattern) 이란?
    Jake Seo
    Jake Seo
    ✔ 잘 보셨다면 광고 한번 클릭해주시면 큰 힘이 됩니다. ✔ 댓글로 틀린 부분을 지적해주시면 기분 나빠하지 않고 수정합니다. ✔ 많은 퇴고를 거친 글이 좋은 글이 된다고 생각합니다. ✔ 간결하고 명료하게 사람들을 이해 시키는 것을 목표로 합니다.

    티스토리툴바