[디자인패턴] 브릿지 패턴 (Bridge Pattern)

koline·2023년 8월 18일
0

디자인패턴

목록 보기
7/24

브릿지 패턴


기능의 클래스 계층과 구현의 클래스 계층을 연결하고, 구현부에서 추상 계층을 분리하여 추상화된 부분과 실제 구현 부분을 독립적으로 확장할 수 있는 패턴이다.

즉, 추상적인 것과 구체적인 것을 분리하여 각자 독립적으로 변형이 가능하고 확장이 가능하도록 하는 패턴이다.

구현뿐만 아니라, 추상화된 부분까지 변경해야 하는 경우 활용한다.



구성 요소


  • Abstraction

기능 계층의 최상위 클래스로 추상 인터페이스를 정의합니다.
구현 부분에 해당하는 클래스 인스턴스를 가지고 해당 인스턴스를 통해 구현부분의 메서드를 호출합니다.

  • RefinedAbstraction

Abstraction에 의해 정의된 인터페이스를 확장합니다.
기능 계층에서 새로운 부분을 확장한 클래스입니다.

  • Implemetor

구현 클래스를 위한 인터페이스를 정의합니다.
Abstraction의 기능을 구현하기 위한 인터페이스를 정의합니다.

  • ConcreteImplementor

Implementor 인터페이스를 구현하여 실제 기능을 구현한다.



구현


// Pizza.java (Implementor)
public interface Pizza {
    String assemble();
}

// PepperoniPizza.java (ConcreteImplementor)
public class PepperoniPizza implements Pizza {
    @Override
    public String assemble() {
        return "Hi I'm PepperoniPizza";
    }
}

// VeggiPizza.java (ConcreteImplementor)
public class VeggiePizza implements Pizza {
    @Override
    public String assemble() {
        return "Hi I'm VeggiePizza";
    }
}

Implementor는 구현 클래스 계층으로서 인터페이스로 구현하여 인터페이스(피자)를 정의하고 ConcreteImplementor에서 해당 인터페이스를 상속받아 각 클래스에 맞게 구현한다.

// Restaurant.java (Abstraction)
public abstract class Restaurant {
	// 브릿지 역할**
    protected Pizza pizza;

    protected Restaurant(Pizza pizza) {
        this.pizza = pizza;
    }

    public abstract String serve();
}

// AmericanRestaurant.java (RefinedAbstraction)
public class AmericanRestaurant extends Restaurant {
    
    public AmericanRestaurant(Pizza pizza) {
        super(pizza);
    }

    @Override
    public String serve() {
        return "[American Restaurant] " + pizza.assemble();
    }
}

// ItalianRestaurant.java (RefinedAbstraction)
public class ItalianRestaurant extends Restaurant {
    
    public ItalianRestaurant(Pizza pizza) {
        super(pizza);
    }

    @Override
    public String serve() {
        return "[Italian Restaurant] " + pizza.assemble();
    }
}

Abstraction은 기능 클래스 계층으로 구현 계층의 클래스(피자)의 인스턴스를 가지고 인스턴스를 생성하고 기능을 추상 메서드로 정의한다. 그리고 RefinedAbstraction에서 구현 클래스 계층의 인스턴스를 받아 상위 클래스(Abstraction)에 전달해 인스턴스화하고 해당 클래스의 기능을 세부적으로 구현한다.

// Client.java
public class Client {
    public static void main(String[] args) {

        Restaurant american = new AmericanRestaurant(new PepperoniPizza());
        System.out.println(american.serve());

        Restaurant italian = new ItalianRestaurant(new VeggiePizza());
        System.out.println(italian.serve());
    }
}

// 출력 결과
[American Restaurant] Hi I'm PepperoniPizza
[Italian Restaurant] Hi I'm VeggiePizza




사용하는 이유


예를 들어 위의 예시코드의 경우 브릿지 패턴을 사용하지 않을 경우 총 4개의 클래스가 필요하게 된다(italian-pepperoni, italian-veggie, american-pepperoni, american-veggie). 위의 예시코드에도 사용된 클래스는 4개 이지만, 만약 피자의 종류가 하나 추가될 경우 브릿지 패턴에서는 Pizza 인터페이스를 상속받는 새로운 피자 클래스를 하나 추가하면 되지만, 브릿지 패턴을 사용하지 않을 경우에는 italian-새로운피자, american-새로운피자 2개의 클래스가 추가되며, 이후 레스토랑을 추가할 경우 3개의 클래스(피자 종류가 3개) 이런 식으로 추가해야 할 클래스가 기하급수적으로 늘어나게 된다.

이러한 이유로 피자를 만드는 구현 클래스 계층과, 피자를 주문받고 제작해 서빙하는 기능 클래스 계층을 분리하여 각 계층이 독립적으로 확장될 수 있게하는 패턴이다.



참고


[디자인패턴] 디자인패턴이란? - 생성패턴, 구조패턴, 행위패턴

[디자인패턴]브릿지 패턴이란?

[Java][디자인 패턴] 8. 브리지 패턴 (Bridge Pattern)

profile
개발공부를해보자

0개의 댓글