Design patterns
어댑터
수색…
어댑터 패턴 (PHP)
다른 유형의 조직에서 특정 루틴을 수행하는 과학 실험을 사용하는 실제 사례입니다. 클래스에는 기본적으로 조직 또는 루틴을 개별적으로 가져 오는 두 개의 함수가 포함되어 있습니다. 이후 버전에서는 새로운 클래스를 사용하여 두 클래스를 모두 가져 오는 함수를 추가했습니다. 즉, 원래 코드를 편집하지 않았으므로 기존 클래스를 손상시킬 위험이 없습니다 (다시 테스트하지 않아도 됨).
class Experiment {
private $routine;
private $tissue;
function __construct($routine_in, $tissue_in) {
$this->routine = $routine_in;
$this->tissue = $tissue_in;
}
function getRoutine() {
return $this->routine;
}
function getTissue() {
return $this->tissue;
}
}
class ExperimentAdapter {
private $experiment;
function __construct(Experiment $experiment_in) {
$this->experiment = $experiment_in;
}
function getRoutineAndTissue() {
return $this->experiment->getTissue().' ('. $this->experiment->getRoutine().')';
}
}
어댑터 (Java)
귀하의 현재 코드베이스에는 다음과 같은 MyLogger
인터페이스가 있다고 가정합니다 :
interface MyLogger {
void logMessage(String message);
void logException(Throwable exception);
}
MyFileLogger
및 MyConsoleLogger
와 같이 이들에 대한 몇 가지 구체적인 구현을 작성했다고 가정 해 MyFileLogger
.
응용 프로그램의 Bluetooth 연결을 제어하기위한 프레임 워크를 사용하기로 결정했습니다. 이 프레임 워크에는 다음 생성자가있는 BluetoothManager
가 들어 있습니다.
class BluetoothManager {
private FrameworkLogger logger;
public BluetoothManager(FrameworkLogger logger) {
this.logger = logger;
}
}
BluetoothManager
는 로거도 허용합니다. 그러나 인터페이스가 프레임 워크에 의해 정의 된 로거가 필요하며 함수의 이름을 다르게 지정하는 대신 메소드 오버로드를 사용했습니다.
interface FrameworkLogger {
void log(String message);
void log(Throwable exception);
}
재사용하고 싶은 MyLogger
구현체가 이미 있지만, FrameworkLogger
의 인터페이스에 맞지 않습니다. 어댑터 디자인 패턴이 나오는 곳입니다.
class FrameworkLoggerAdapter implements FrameworkLogger {
private MyLogger logger;
public FrameworkLoggerAdapter(MyLogger logger) {
this.logger = logger;
}
@Override
public void log(String message) {
this.logger.logMessage(message);
}
@Override
public void log(Throwable exception) {
this.logger.logException(exception);
}
}
FrameworkLogger
인터페이스를 구현하고 MyLogger
구현을 수용하는 어댑터 클래스를 정의하면이 기능을 다른 인터페이스간에 매핑 할 수 있습니다. 이제 BluetoothManager
MyLogger
구현과 함께 사용할 수 있습니다.
FrameworkLogger fileLogger = new FrameworkLoggerAdapter(new MyFileLogger());
BluetoothManager manager = new BluetoothManager(fileLogger);
FrameworkLogger consoleLogger = new FrameworkLoggerAdapter(new MyConsoleLogger());
BluetoothManager manager2 = new BluetoothManager(consoleLogger);
Java 예제
SWT MouseListener 및 MouseAdapter 클래스에서 Adapter 패턴의 훌륭한 기존 예제를 찾을 수 있습니다.
MouseListener 인터페이스는 다음과 같습니다.
public interface MouseListener extends SWTEventListener {
public void mouseDoubleClick(MouseEvent e);
public void mouseDown(MouseEvent e);
public void mouseUp(MouseEvent e);
}
이제 UI를 작성하고 이러한 리스너를 추가하는 시나리오를 상상해보십시오.하지만 대부분의 경우에는 무언가가 클릭 한 번 (mouseUp)이 아닌 다른 것을 신경 쓰지 않습니다. 빈 구현을 끊임없이 만들고 싶지는 않을 것입니다.
obj.addMouseListener(new MouseListener() {
@Override
public void mouseDoubleClick(MouseEvent e) {
}
@Override
public void mouseDown(MouseEvent e) {
}
@Override
public void mouseUp(MouseEvent e) {
// Do the things
}
});
대신 MouseAdapter를 사용할 수 있습니다.
public abstract class MouseAdapter implements MouseListener {
public void mouseDoubleClick(MouseEvent e) { }
public void mouseDown(MouseEvent e) { }
public void mouseUp(MouseEvent e) { }
}
비어있는 기본 구현을 제공함으로써 어댑터에서 신경 쓰는 메소드 만 자유롭게 재정의 할 수 있습니다. 위의 예에서 다음을 수행합니다.
obj.addMouseListener(new MouseAdapter() {
@Override
public void mouseUp(MouseEvent e) {
// Do the things
}
});
어댑터 (UML 및 예제 상황)
더 상상할 수있는 상황에서 어댑터 패턴과 상황을 사용하기 위해 작고 간단하며 매우 구체적인 예가 여기에 제시되어 있습니다. 여기에는 코드가 없으며, UML과 예제 상황과 그 문제에 대한 설명 만있을 것입니다. 물론 UML 컨텐트는 Java와 비슷하게 작성되었습니다. (글쎄, 힌트 텍스트 "좋은 예제는 주로 코드", 나는 디자인 패턴이 너무 다른 방식으로 소개 될 정도로 추상적이라고 생각합니다.)
일반적으로 어댑터 패턴은 호환되지 않는 인터페이스가 있고 그 중 어느 것도 직접 재 작성할 수없는 상황에 적합한 솔루션입니다.
당신이 멋진 작은 피자 배달 서비스를 운영하고 있다고 상상해보십시오. 고객은 웹 사이트에서 온라인으로 주문할 수 있으며 Pizza
를 표현하고 청구서, 세금 보고서 등을 계산할 수있는 클래스 Pizza
를 사용하는 소규모 시스템을 보유하고 있습니다. 피자의 가격은 가격을 (원하는 통화의) 센트로 나타내는 단일 정수로 주어집니다.
귀하의 배달 서비스는 훌륭하게 진행되고 있지만 어느 시점에서 성장하는 고객을 더 이상 처리 할 수는 없지만 여전히 확장하고 싶습니다. 큰 온라인 메타 배달 서비스의 메뉴에 피자를 추가하기로 결정했습니다. 그들은 피자뿐만 아니라 많은 다른 식사를 제공합니다. 따라서 그들의 시스템은 추상화를 더 많이 사용하고 돈을 나타내는 클래스 MoneyAmount
와 함께 나오는 식사를 나타내는 인터페이스 IMeal
습니다.
MoneyAmount
는 쉼표 앞의 금액 (또는 임의의 통화) 하나와 쉼표 뒤의 0에서 99까지의 센트 금액에 대한 입력으로 두 개의 정수로 구성됩니다.
Pizza
의 가격이 총 가격을 센트 (> 99)로 나타내는 단일 정수이기 때문에 IMeal
과 호환되지 않습니다. 이것은 어댑터 패턴이 작동되는 지점입니다. 자신의 시스템을 변경하거나 새로운 시스템을 작성하는 데 너무 많은 노력이 들며 호환되지 않는 인터페이스를 구현해야하는 경우 어댑터 패턴을 적용 할 수 있습니다.
패턴을 적용하는 방법에는 클래스 어댑터와 객체 어댑터의 두 가지가 있습니다.
둘 다 공통적으로 어댑터 ( PizzaAdapter
)가 새로운 인터페이스와 적응 자 (이 예에서는 Pizza
사이의 일종의 변환기로 작동한다는 것을 공통적으로 가지고 있습니다. 어댑터는 새로운 인터페이스 ( IMeal
)를 구현 한 다음 Pizza
를 상속 받고 자체 가격을 하나의 정수에서 2 (클래스 어댑터)로 변환합니다.
또는 Pizza
유형의 객체를 속성으로 가지며 그 값 (객체 어댑터)을 변환합니다.
어댑터 패턴을 적용하면 호환되지 않는 인터페이스간에 "변환"할 수 있습니다.