본문 바로가기
Design Pattern/구조 패턴(Structural Patterns)

브리지(Bridge) 패턴 - 구조 패턴 (Structural Patterns)

by 김 민 준 2024. 5. 23.

 

브리지 패턴은 추상화와 구현을 분리하여 둘을 독립적으로 확장할 수 있도록 하는 디자인 패턴이다. 

 

여러 모양과 색상이 있다고 가정해보자.

 

빨간색 원

파란색 사각형

 

모양과 색상을 조합하는 모든 경우를 각각 클래스로 정의하면 클래스의 수가 기하급수적으로 늘어난다.

브리지 패턴을 사용해서 모양과 색상을 분리하고 이들을 독립적으로 확장 할 수 있도록 해보자.

 

Shape 클래스는 추상화 역할을 한다.

// Shape 클래스: 추상화 역할
abstract class Shape {
    protected Color color;

    protected Shape(Color color) {
        this.color = color;
    }

    public abstract void draw();
}

 

Color 인터페이스는 구현 역할을 한다.

 

// Color 인터페이스: 구현 역할
interface Color {
    void applyColor();
}

 

Color 구현 클래스는 빨간색과 파란색을 구체적으로 구현한다.

 

// RedColor 클래스: 구체적인 구현
class RedColor implements Color {
    @Override
    public void applyColor() {
        System.out.println("Applying red color.");
    }
}

// BlueColor 클래스: 구체적인 구현
class BlueColor implements Color {
    @Override
    public void applyColor() {
        System.out.println("Applying blue color.");
    }
}

 

Shape 구현 클래스는 원과 사각형과 같은 모양이다.

 

// Circle 클래스: 구체적인 추상화
class Circle extends Shape {
    public Circle(Color color) {
        super(color);
    }

    @Override
    public void draw() {
        System.out.print("Drawing Circle. ");
        color.applyColor();
    }
}

// Square 클래스: 구체적인 추상화
class Square extends Shape {
    public Square(Color color) {
        super(color);
    }

    @Override
    public void draw() {
        System.out.print("Drawing Square. ");
        color.applyColor();
    }
}

 

이를 통해서 브리지 패턴을 사용하면 아래 코드와 같이 사용할 수 있다. 

 

// 사용 예시
public class BridgePatternDemo {
    public static void main(String[] args) {
        Shape redCircle = new Circle(new RedColor());
        Shape blueSquare = new Square(new BlueColor());

        redCircle.draw();  // 출력: Drawing Circle. Applying red color.
        blueSquare.draw(); // 출력: Drawing Square. Applying blue color.
    }
}

 

형태를 나타내며 색상을 적용하는 추상 매서드 draw()를 정의한다.

Color는 applyColor()를 정의한다. 

Cicle, Square는 구체적인 추상화 역할을 한다. 

브리치 패턴을 사용하여 모양과 색상을 분리하여 독립적으로 확장 할 수 있다는것을 확인 할 수 있다.

 

실무에서는 어떤경우에 브리지 패턴을 사용할까?

 

예를 들어 리포트기능을 만들어야 한다고 생각해보자. 리포트는 PDF 파일 그리고 HTML파일로 포맷하는 기능이 필요하다. 

 

 

리포트 포맷 인터페이스는 구현 역할을 한다.

// ReportFormat 인터페이스: 리포트 포맷의 공통 기능 정의
interface ReportFormat {
    void generate(String content);
}

 

HTML 리포트와 PDF리포트에 대해 클래스를 만든다.

// HTMLReport 클래스: 구체적인 HTML 리포트 포맷
class HTMLReport implements ReportFormat {
    @Override
    public void generate(String content) {
        System.out.println("Generating HTML report with content: " + content);
    }
}

// PDFReport 클래스: 구체적인 PDF 리포트 포맷
class PDFReport implements ReportFormat {
    @Override
    public void generate(String content) {
        System.out.println("Generating PDF report with content: " + content);
    }
}

 

리포트의 공통 기능을 만든다. 이는 추상화 역할을 한다.

// Report 클래스: 리포트의 공통 기능 정의
abstract class Report {
    protected ReportFormat format;

    protected Report(ReportFormat format) {
        this.format = format;
    }

    public abstract void createReport(String content);
}

 

구체적인 리포트 클래스를 만든다.

// SalesReport 클래스: 구체적인 리포트
class SalesReport extends Report {

    public SalesReport(ReportFormat format) {
        super(format);
    }

    @Override
    public void createReport(String content) {
        format.generate(content);
    }
}

 

이렇게 만든 리포트 관련 소스코드를 어떻게 사용하는지는 아래 코드를 확인해보자

 

// 사용 예시
public class BridgePatternDemo {
    public static void main(String[] args) {
        ReportFormat htmlFormat = new HTMLReport();
        ReportFormat pdfFormat = new PDFReport();

        Report htmlSalesReport = new SalesReport(htmlFormat);
        Report pdfSalesReport = new SalesReport(pdfFormat);

        // HTML 포맷의 판매 보고서 생성
        htmlSalesReport.createReport("Sales Data for 2023");  // 출력: Generating HTML report with content: Sales Data for 2023

        // PDF 포맷의 판매 보고서 생성
        pdfSalesReport.createReport("Sales Data for 2023");   // 출력: Generating PDF report with content: Sales Data for 2023
    }
}

 

실제 현업에서 사용하는 소스코드는 아니지만 HTML과 PDF에 사용할 content의 format을 분리하여 각각 독립적으로 확장할 수 있는 베이스 코드를 확인했다.