의도
- 큰 클래스 또는 밀접하게 관련된 클래스 집합을 두 개의 개별 계층구조로 나누어 독립적으로 개발할 수 있도록 하는 구조 디자인 패턴
문제
- 원과 직사각형 모양이 있는 Shape 클래스가 있다 가정해보자
- Shape 클래스를 확장해 빨강, 파란색이 있는 원, 사각형을 만들고자 한다.
- 지금 당장이야 괜찮을지 몰라도 유형들이 많아지면 많아질수록 코드가 복잡해지게 된다.
해결책
- 객체를 상속하지 말고 합성을 하여 문제를 해결할 수 있음
- 여러 차원 중 하나를 별도의 클래스 계층구조로 추출해 새 계층구조의 객체를 참조하도록 함
- 색상 관련 코드를 자체 클래스로 추출하고, 모양 클래스에서는 색상 개체를 참조하는 방식을 통해 색상 추가코드를 분리 가능
구조
class Abstraction {
protected implementation: Implementation;
constructor(implementation: Implementation) {
this.implementation = implementation;
}
public operation(): string {
const result = this.implementation.operationImplementation();
return `Abstraction: Base operation with:\n${result}`;
}
}
class ExtendedAbstraction extends Abstraction {
public operation(): string {
const result = this.implementation.operationImplementation();
return `ExtendedAbstraction: Extended operation with:\n${result}`;
}
}
interface Implementation {
operationImplementation(): string;
}
class ConcreteImplementationA implements Implementation {
public operationImplementation(): string {
return 'ConcreteImplementationA: Here\'s the result on the platform A.';
}
}
class ConcreteImplementationB implements Implementation {
public operationImplementation(): string {
return 'ConcreteImplementationB: Here\'s the result on the platform B.';
}
}
function clientCode(abstraction: Abstraction) {
console.log(abstraction.operation());
}
let implementation = new ConcreteImplementationA();
let abstraction = new Abstraction(implementation);
clientCode(abstraction);
console.log('');
implementation = new ConcreteImplementationB();
abstraction = new ExtendedAbstraction(implementation);
clientCode(abstraction);
적용
- 기능의 여러 변형들을 분리하고 정리하고자 할 때 사용
클래스의 크기가 커지면 작동 방식 파악과 리팩토링이 어려워짐
브리지 패턴을 사용해 클래스를 여러 계층구조로 쪼개 유지관리를 용이하게 함
- 독립적인 차원에서 클래스를 확장하고자 할 때 사용
원래 클래스를 내비두고 새로운 계층구조의 클래스만 수정 가능
- 런타임에 구현을 전환할 수 있어야 할 때 사용
필요하다면 브리지 패턴을 사용해 필드값을 바꾸는 것 만으로도 추상화 내부의 구현 객체를 바꿀 수 있음
구현 방법
- 클래스에서 직교 차원 식별
추상화, 플랫폼, 인터페이스, 구현 등 여러가지가 있음
- 클라이언트가 필요로 하는 작업들을 확인하고 기초 추상 클래스에서 정의
- 모든 플랫폼들에 제공되야 하는 작업들을 결정하고 이를 구현 인터페이스에서 선언함
- 도메인의 모든 플랫폼에 대해 구상 구현 클래스들을 생성하고 구현 인터페이스를 따르도록 함
- 추상화 클래스 내에서 구현 유형에 대한 참조 필드를 추가함
- 상위 수준 논리의 변형들이 여러개 있으면 기초 추상화 클래스를 확장해 변형된 클래스 생성
- 클라이언트 코드는 구현 객체를 추상화에 생성자에 전달해 연관시켜야 함
장단점
- 플랫폼 독립적인 클래스, 앱 제작 가능
- 클라이언트 코드는 상위수준의 추상화를 통해 작동하며, 플랫폼 세부 정보에 노출되지 않음
- 새로운 추상화 클래스와 구현 클래스를 상호 독립적으로 도입해 개방, 폐쇄 원칙 및 단일 책임 원칙 준수
- 결합도가 높은 클래스에 패턴을 적용할 경우 코드가 더 복잡해질 수 있음
출처:
https://refactoring.guru/ko/design-patterns/bridge